<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2948438400037317662</id><updated>2011-12-27T13:23:46.203+01:00</updated><category term='C++'/><category term='Me'/><category term='Xbox360'/><category term='Gaming'/><category term='PS3'/><category term='English'/><category term='Radon Labs'/><category term='History'/><category term='Cell'/><category term='Rant'/><category term='Nebula'/><category term='Game Development Essentials'/><category term='Nebula3'/><title type='text'>The Brain Dump</title><subtitle type='html'>Game development, Nebula Device, personal mumblings...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default?start-index=101&amp;max-results=100'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>140</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9127122815785539028</id><published>2011-06-02T14:43:00.001+01:00</published><updated>2011-06-02T14:43:26.385+01:00</updated><title type='text'>Year’s Roundup</title><content type='html'>&lt;p&gt;I will always remember the past year as the time when we did an “MMO in 8 months”. 15 months ago I would have laughed about the hubris of the thought alone. Yet here we are, &lt;a href="http://www.drakensangonline.com"&gt;Drakensang Online&lt;/a&gt; is going into open beta soon, in fact you can register now and should be able to start playing soon after, since new registrations are now unlocked automatically after at most a few hours. The term MMO is debatable of course. MMO is such a terribly heavy word. MMO has become another term for a “300-million-$ budget, 5-years-in-the-making, overambitious WoW-wanna-be fiasco”. &lt;/p&gt;  &lt;p&gt;Drakensang is none of that, and that’s why I hesitate to call it an MMO because the term is loaded with wrong assumptions. But if you look at the technical side of things, Drakensang Online *is* an MMO. But it does many things different then old-school MMOs: it runs in the browser, it doesn’t require a huge front-end download (with an average DSL line you’re up and running after about 30 seconds and we’re working on improving that further), it is free-to-play, it has an action-combat system - but technically it’s still an MMO.&lt;/p&gt;  &lt;p&gt;I’m incredibly proud of being part of the Drakensang team and Bigpoint, because the whole “MMO in 8 months” thing wouldn’t have been possible with any other team and without building on Bigpoint’s existing infrastructure and learning from the original F2P gurus. And I’d like to believe that Nebula3 also played its little role by providing a solid code base for the client and game server. &lt;/p&gt;  &lt;p&gt;Of course what Drakensang is today is only the beginning. Without having to worry about Gold Masters, patch distribution, or slow TRC/TCR/Lotchecks we currently have a production pipeline in place where we can manage a weekly release cycle and we plan to keep that cycle for the foreseeable future to fix bugs, improve performance and tweak the game play. Big new content releases are on the horizon which will expand the world of Duria with new regions, antagonists and playable character classes, items, skills, etc... “Relase early, release often, and listen to your customers” - indeed.&lt;/p&gt;  &lt;p&gt;In the mean time, Nebula3 has gained a few interesting new features:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;An improved, multithreaded HTTP “virtual file system”, with zlib compression, MD5-hashes for fine-grained local caching, CDN support and background-preloading. Instead of downloading a few big bundle files, our client fires HTTP GET requests when a file is needed (and is not in the cache). Requests are prioritized and handled by several threads, so that large low-priority downloads don’t block small high-priority downloads, and several HTTP GET requests can be in flight at the same time – but since all of this is wrapped in a “virtual filesystem”, the same client can load all of its data from disc as in the olden days without changing a single line of code. &lt;/li&gt;    &lt;li&gt;We ditched our own Tcl based meta-build-system and went with CMake instead.&lt;/li&gt;    &lt;li&gt;We also got rid of Maya as our level editor and wrote our own WYSIWYG editor.&lt;/li&gt;    &lt;li&gt;The Foundation Layer has been ported to Linux, and is the base for our game server&lt;/li&gt;    &lt;li&gt;We have added wrapper addons for FMOD, FreeType, MySQL, PathEngine, and several Bigpoint-internal APIs.&lt;/li&gt;    &lt;li&gt;The RakNet-based Network addon has been overhauled and is the basis for our client/server code.&lt;/li&gt;    &lt;li&gt;The graphics subsystem now supports hardware-instanced rendering to efficiently render many instances of a graphics entity in a single draw call (that’s how we keep the drawcalls under control for our Drakensang maps, from thousands of draw calls down to about 200..300 drawcalls).&lt;/li&gt;    &lt;li&gt;Character models can now be baked, no matter what equipment a character wears, it’s always rendered in a single draw call (actually two drawcalls because of the depth/normal- and material-passes of the Pre-Light-Pass renderer).&lt;/li&gt;    &lt;li&gt;The shader code has been refactored for better portability and moved into its own subsystem.&lt;/li&gt;    &lt;li&gt;The realtime-shadow system has been cleaned up and optimized.&lt;/li&gt;    &lt;li&gt;A new, modern decal system. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Compared to all the new server and client code these changes are relatively small though.&lt;/p&gt;  &lt;p&gt;The completely dynamic lighting and shadowing, and the new decal system help us to hide the fact that our maps are made from many small tiles, and the hardware instancing helps us to render thousands of visible models efficientely. All of these features have been implemented for the single, most important requirement of the Drakensang Online client: to keep the download size of assets as small as possible. While our offline Drakensang titles were about 4.5 GByte in size, all of Drakensang Online currently fits into about 100 MByte, and only a fraction of this is required upfront to start playing. A nice side effect of this hardcore data optimization is that loading times between maps are almost non-existent. If the data is already in the download-cache a map transition takes about one or two second, but even if the data must be streamed it rarely takes longer then 5 or 10 seconds until everything has been streamed – in the old Drakensang we struggled to keep loading times under 40 seconds - from the local hard disc!&lt;/p&gt;  &lt;p&gt;In my spare time I also played around with Nebula3 on iOS, up to the point where I’m able to render a Drakensang Online map on the iPhone4 and iPad at about 30 fps in full display resolution. For the Foundation Layer I’m actually using the Linux port with very minor changes, the Render Layer has been ported to OpenGL ES 2.0, and I had to be a bit creative to make up for the missing hardware-instancing. The fill rate of those devices is not enough to support any type of deferred shading, so I went for a simple forward-renderer with one dynamic light source. Maybe the next batch of mobile GPUs will be powerful enough for the light-pre-pass renderer, since it actually is not as demanding on fillrate as other deferred shading solutions. I also played around a bit with the Android SDK, but the whole iOS development process is so much more streamlined that I didn’t get very far yet. It’s just more productive and enjoyable to write, debug and profile with XCode and the iOS SDK then with the Android SDK (even *with* the braindead code-signing bullshit required on the iPhone). Eventually I hope to find some time to port N3 to Google’s &lt;a href="http://code.google.com/chrome/nativeclient/"&gt;NaCl&lt;/a&gt;, which in my opinion is the most interesting project coming out of Google EVAAAR on several levels (not just for browser-games but for more secure native code in general).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9127122815785539028?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9127122815785539028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9127122815785539028' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9127122815785539028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9127122815785539028'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2011/06/years-roundup.html' title='Year’s Roundup'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6123964020227224152</id><published>2010-06-16T20:26:00.001+01:00</published><updated>2010-06-16T20:26:34.028+01:00</updated><title type='text'>Kinectifail</title><content type='html'>&lt;p&gt;I feel embarrassed for my &lt;a href="http://flohofwoe.blogspot.com/2009/06/tidbits.html"&gt;Project Natal hype&lt;/a&gt; last year in light of Microsoft’s terrible E3 2010 conference. One year ago, Project Natal showed promise and potential, with its incredibly cool technology it could have been the next big thing, and Microsoft had more then enough time to prepare the ultimate killer application for Natal. Turns out these “killer applications” are a bunch of mini-games we’ve already seen 4 years before on the Wii. If the dashboard looks more interesting then the games on your &lt;strong&gt;gaming platform &lt;/strong&gt;it’s really time to start worrying me thinks. &lt;/p&gt;  &lt;p&gt;The new video chat, video player with voice control, dashboard with quick-links to the most useful areas, THAT’s really cool stuff. I wish everything on my TV would control like that instead of having all those remote controls with dozens of buttons (although I’m a bit disappointed about that “mouse-pointer emulation”, I was hoping for some sort of Minority Report “swooosh interface” instead of a point’n’click interface). Probably still not enough to make me buy, since the game pad is still “good enough” for menu navigation. A whole lot depends on the price. I feel somewhere around 79 Euros would be a good price point – yeah I know, just kidding haha.&lt;/p&gt;  &lt;p&gt;But what happened to the cool games which really show the potential of full-body motion control? And what market is MS going after? And who green-lighted this terrible name “Kinect”? I don’t know what the native English speakers think about the name, but to a German “Kinect” is just like Knnnn….HÄH? And even after carefully decoding the sequence of characters the spoken name sounds like some industrial “middleware” device Siemens or Bosch would produce for car-manufacturers to built into their engine or gearbox. Makes the name Wii sound ingenious in retrospect. Or Move, easy, simple, to the point, even for non-English speakers.&lt;/p&gt;  &lt;p&gt;So who should buy Kinect? The general idea of motion control is old news which was cool around 2 years ago, and (unfortunately) Kinect does too little to set itself apart with the presented launch titles. Sure, the technology is incredibly cool – to a technology nerd. But who cares about little details like… that maybe you have a little bit more control about your virtual bowling ball with Kinect compared to a Wiimote? Maybe the hardcore guys who know about those technical details (but usually don’t care about virtual bowling). To “normal people” this is just as interesting as the difference between a turbo and a compressor. People who like to play sports mini games while getting drunk at parties already got their fix with the Wii, and I can’t imagine that they’re so hot for a marginally better bowling experience that they’re defecting to the 360 en mass.&lt;/p&gt;  &lt;p&gt;And here’s another strange thing: if MS is chasing the casual crowd all of the sudden, why is the Xbox redesign so “hardcore eXtreme”? It’s dark and edgy and looks menacing and dangerous. It says “buy me – if you dare”. I think that’s not quite the right message for mom and dad to buy an Xbox and play some bowling with the kids.&lt;/p&gt;  &lt;p&gt;I honestly don’t understand why MS didn’t secure a real-time strategy title and created a breathtaking motion control interface to show-off for E3. “Real-time strategy on the console done right”. Throw a couple o’millions at Blizzard to get Starcraft II onto the 360 with really innovative motion controls. Now I’m just being silly, but I’m sure THAT would have turned a few heads, mayhaps even convert some hardcore PCers to the 360.&lt;/p&gt;  &lt;p&gt;So yeah… I reeeeally can’t see myself jumping around a lot in front of my TV. New Xbox looks cool though, but I’ll wait until it is available in white.&lt;/p&gt;  &lt;p&gt;-Floh.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6123964020227224152?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6123964020227224152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6123964020227224152' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6123964020227224152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6123964020227224152'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2010/06/kinectifail.html' title='Kinectifail'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-8031338357616892149</id><published>2010-06-06T11:24:00.001+01:00</published><updated>2010-06-06T11:24:08.241+01:00</updated><title type='text'>Radon Labs R.I.P. 2000-2010</title><content type='html'>&lt;p&gt;Just a quick update, because I don’t have a lot of time for blogging at the moment. As you may have noticed, Radon Labs is no more. The plug was pulled on the planned financing model for the next Drakensang, and in the end we had to pull the plug on the company. The good news in all of this is that there were a lot of interested companies to help us keep the ball rolling, and since Tuesday last week we’re a part of Bigpoint which opens up a lot of new, very interesting directions where Drakensang and the technology behind it will move in the future (obvious hint: the net may play a very important role). Unfortunately it’s too early for me to answer questions regarding Nebula in any meaningful way. We’re currently busy getting to know our new comrades, plotting strategies and making plans.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-8031338357616892149?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/8031338357616892149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=8031338357616892149' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8031338357616892149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8031338357616892149'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2010/06/radon-labs-rip-2000-2010.html' title='Radon Labs R.I.P. 2000-2010'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-528900715511659843</id><published>2010-04-24T15:45:00.001+01:00</published><updated>2010-04-24T15:51:44.649+01:00</updated><title type='text'>Splinter Cell Conviction</title><content type='html'>&lt;p&gt;As an old-time Splinter Cell fan(atic) I’m happy to report that the new SC kicks ass big time! I was expecting the worst, because of its troubled and lengthy production (“back to the drawing board” etc…). After the demo there was much lamenting among Splinter Cell veterans, and the demo left me a bit worried as well, there didn’t seem too much left of the original Splinter Cell formula, and there was too little stealth and too much action. But after playing through the single player campaign twice now (first on Normal difficulty, then on Realistic) I think that the SC team went the right way with most changes.&lt;/p&gt;  &lt;p&gt;At least in Realistic mode it is still very important to be stealthy, but (and that’s the important part) if stealth is broken, the game play doesn’t break down too. In previous SC’s (including the nearly perfect Chaos Theory – which by the way still looks phenomenal on the 360) I was often tempted to restart at the last checkpoint when open combat broke loose, because everything became just too messy.&lt;/p&gt;  &lt;p&gt;In Conviction, the transition from stealth to combat and back actually works, and it’s really fun to play in this new way. That’s the one big - most important (and most risky) - change the SC team got exactly right. &lt;/p&gt;  &lt;p&gt;What Conviction does *mostly* right is that it steers the franchise back onto a clear course which seemed to be lost after Chaos Theory. Double Agent added more and more bells and whistles (like all those utterly useless mini games) and Conviction looked like it didn’t know where to go as well before the reboot. The rebooted Conviction reduces this mess back into a nice, small set of game play features. Almost a little bit too streamlined for my liking (you can’t drag around bodies anymore, you can’t choose between fatal and non-fatal take-downs, and I actually liked that one lock-picking mini game), but the new agility of Sam Fisher, and the Mark-&amp;amp;-Execute feature makes up for the losses.&lt;/p&gt;  &lt;p&gt;And sometimes there’s a workaround for missing features. For instance, instead of dragging a dead or unconscious body like in the old Splinter Cells, one can choke-hold a guard and instead of using him as a meat-shield, drag him into a dark corner and take him out there so surveillance cameras and other guards won’t find the body. But finding those new twists is probably harder for gamers who played the old Splinter Cells then for new gamers.&lt;/p&gt;  &lt;p&gt;But once the player has learned to use Sam’s new skills without having to think about them, the game play experience is phenomenal. There’s nothing more satisfying then cleaning up half of the guards in a room with the new Mark-&amp;amp;-Execute, vanish again by dropping a flash-bang, flank the confused remaining guards and taking them out one by one by sneaking up on them from behind.&lt;/p&gt;  &lt;p&gt;I have to confess that in my first play-through I often had to shoot my way out because I didn’t pay enough attention to the environment. There’s almost always a way to solve a situation stealthy, like a water-pipe on the wall or hidden passages to get above or behind the attackers. In the second play-through I already knew the basic layout of the levels, took my time to look around and explore the environment, and I was forced to plan my tactics more thoroughly because of the harder difficulty. The result was that I played much more with stealth, and always had a fallback plan in mind when the situation got out of control.&lt;/p&gt;  &lt;p&gt;It’s also interesting to see how the big 3 Clancy games (Splinter Cell, Rainbow Six and Ghost Recon) are starting to share features that work well. Splinter Cell now uses the phenomenal cover system of the Rainbow Six Vegas games, and the Mark-&amp;amp;-Execute feature is similar to the Rainbow Six marking of priority targets before room-entry. I hope the next Ghost Recon will do similar things. The other 2 games could learn a bit from Sam Fisher’s agility, like jump-sliding over and under obstacles.&lt;/p&gt;  &lt;p&gt;Story’s a bit… well, there is a story and at least it doesn’t get into the way of the actual game ;)&lt;/p&gt;  &lt;p&gt;So all in all, really great game and I didn’t even dive that much into the Co-op and Deniable Ops modes yet…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-528900715511659843?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/528900715511659843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=528900715511659843' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/528900715511659843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/528900715511659843'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2010/04/splinter-cell-conviction.html' title='Splinter Cell Conviction'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4482530615869172742</id><published>2010-04-23T15:47:00.001+01:00</published><updated>2010-04-23T17:33:31.412+01:00</updated><title type='text'>Build Pipeline</title><content type='html'>&lt;p&gt;I’m really happy how far we’ve come along with our build pipeline in the past months. We now have a truly &lt;strong&gt;multi-project, multi-platform, distributed&lt;/strong&gt; build pipeline for our daily builds along with a common programming framework for build tools and a few C# GUI tools which simplify its usage and generally are more pleasing to the eye then a raw DOS shell window.&lt;/p&gt;  &lt;p&gt;Let’s start with the &lt;strong&gt;multi-project&lt;/strong&gt; aspect. At Radon Labs there are usually several projects in flight at the same time. All projects are based on Nebula (but not all are running on top of Nebula3, we may decide to start a project on the older Nebula2/Mangalore if it makes sense). We always had a standardized project structure, daily builds, and rules how a project’s build script looks like but we had to deal with a few detail problems which were often pushed into the future because there were more important problems to fix. One of the fairly critical problems was a proper toolkit version history and more flexible toolkit update process. In the past we only had one current toolkit version, which was updated through a patching process. Toolkit updates are very frequent, from about once a week to a few times per day. It may happen that a new toolkit version breaks file format compatibility with older version. That’s less regularly, maybe once every few months. But this is becoming a problem if a project decides to create an engine branch and thus is decoupled from engine development on the main branch. Makes sense if the project is going into beta and stability is more important then new engine features. Problem is, that the project may come to a point where the toolkit can no longer be updated with the latest version from the main branch, because the main branch introduced some incompatibility.&lt;/p&gt;  &lt;p&gt;What’s needed is that the lead programmer may “pin” a specific toolkit version to his project. We solved this problem with a new “Toolkit Manager” tool which tracks a history of previous versions and which takes care that the latest, or the “right” toolkit version is installed:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_cWdorEDEaNg/S9Gy46vaKvI/AAAAAAAAAJc/lVoDfXMnw9k/s1600-h/toolkit_expanded%5B17%5D.jpg"&gt;&lt;img title="toolkit_expanded" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="552" alt="toolkit_expanded" src="http://lh5.ggpht.com/_cWdorEDEaNg/S9Gy5eTOWPI/AAAAAAAAAJg/CQAruO4b4kA/toolkit_expanded_thumb%5B15%5D.jpg?imgmax=800" width="329" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;When switching to a new project, the Toolkit Manager automatically installs the right toolkit version (only if necessary), but it’s also possible to manually select and install a specific toolkit version. &lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;multi-platform&lt;/strong&gt; aspect of our build pipeline lets us create optimized data builds for the various platforms (currently Win32/D3D9, Xbox360, PS3, Wii and the legacy Nebula2 “software platform”) from the same assets with a single “flip of a switch”. From the outside the build system on a workplace machine is represented by a very simple front-end tool, the new “N3 Batcher”:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/S9Gy5xO7PxI/AAAAAAAAAJk/T5-7Gj3VgbY/s1600-h/n3batcher%5B4%5D.jpg"&gt;&lt;img title="n3batcher" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="454" alt="n3batcher" src="http://lh5.ggpht.com/_cWdorEDEaNg/S9Gy6ZWmcBI/AAAAAAAAAJo/Of_y8LDt_5s/n3batcher_thumb%5B2%5D.jpg?imgmax=800" width="679" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The UI is hopefully self-explanatory, except maybe for the “Sync” build task. This performs a data-sync with the latest daily build from the project’s build server before exporting locally modified data which saves quite a bit of time in large projects with many day-to-day changes.&lt;/p&gt;  &lt;p&gt;Under the hood the build system looks a bit more complex, but follows a clean layer model:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_cWdorEDEaNg/S9Gy7KVLnCI/AAAAAAAAAJs/FF7YA80_OtI/s1600-h/N3BuildPipelineOverview%5B5%5D.png"&gt;&lt;img title="N3BuildPipelineOverview" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="398" alt="N3BuildPipelineOverview" src="http://lh5.ggpht.com/_cWdorEDEaNg/S9Gy7iYVxmI/AAAAAAAAAJw/u45OVUwn9n0/N3BuildPipelineOverview_thumb%5B3%5D.png?imgmax=800" width="688" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;At the top there’s the “N3 Batcher” front-end tool for workplaces, and the “makedistro” MSBuild script for the master build server which provides the daily build.&lt;/p&gt;  &lt;p&gt;Those 2 front-ends don’t do much more then calling a centralized “buildassets” MSBuild script which takes care of build steps that are identical for all projects. If project-specific build-steps are necessary they are defined in a projectspecific.msbuild script which is located in the project directory.&lt;/p&gt;  &lt;p&gt;The build scripts split the build process into several build tasks which form a dependency tree. Build tasks mainly call the Nebula3 command line tools, which in turn are often just wrappers for platform specific build tools provided by the various platform SDKs. For instance, you can simply call N3’s texturebatcher3 tool with the “-platform xbox360” argument to convert textures for the Xbox360 platform, or with “-platform ps3” to convert textures into the PS3 format (provided the Xbox360 and PS3 SDKs are installed on the build machine – of course). Another important task of the N3 command line tools is that they distribute the build jobs across multiple cores, and multiple build machines (more on that below).&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The main result of the build process are platform-specific archive files which contain all the build data for one project (the actual daily build process also compiles the executable, creates an installer, and optionally uploads the finished build to the publisher’s FTP server).&lt;/p&gt;  &lt;p&gt;All exported data is neatly separated by platform into separate directories to enable incremental builds for different platforms on the same build machine.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Distributed Builds:&lt;/strong&gt; For the daily build dogma, a complete build must be finished during a single night. In Drakensang we hit this 12-hour ceiling several times until we reached a point where we couldn’t improve build time by throwing faster hardware at the problem. Thus we decided that we need a distributed build system. Evaluating existing systems wasn’t very fruitful (mind you, this is not about distributing code compilation, but distributing the process of exporting graphics objects, textures and other data), thus we considered building our own system. The most important task was to create a good tools framework, which makes it easier to create distributed tools in the future. The result of this is the DistributedToolkitApp class, which does all the hard work (distributing build tasks across CPU cores and across several machines). Tools created with this class basically don’t need to care whether they run locally or distributed, where the input data comes from and where the output goes to. They only need to worry about the actual conversion job. Of course there’s a lot of necessary standardization underneath, for instance how a “build job” is exactly defined, and some restrictions about input and output data, but defining these standards and rules wasn’t much of a problem. What surprised me most was how many small problems showed up until the distributed build system was robust enough for a real-world project. I’ve been under the impression that a TCP/IP connection inside a LAN is a relatively fool-proof way to communicate. Well, it worked “most of the time”, but we also had a lot of over-night builds break because of mysterious connection issues until we built more fault-tolerance into the communication (like automatic re-connection, or putting “vanished” build slaves onto a black-list). Well, it works now, and its relatively simple to maintain such a build cluster.&lt;/p&gt;  &lt;p&gt;PS: we really need to update our tools icons though…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4482530615869172742?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4482530615869172742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4482530615869172742' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4482530615869172742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4482530615869172742'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2010/04/build-pipeline.html' title='Build Pipeline'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_cWdorEDEaNg/S9Gy5eTOWPI/AAAAAAAAAJg/CQAruO4b4kA/s72-c/toolkit_expanded_thumb%5B15%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-8631878902381880007</id><published>2010-03-27T15:35:00.003+01:00</published><updated>2010-03-27T15:55:32.259+01:00</updated><title type='text'>It's Not So Grim Up North</title><content type='html'>I spent a wonderful day at the 2010 Grad Show of &lt;a href="http://www.ltu.se/ske"&gt;LTU Skellefteå&lt;/a&gt; in Northern Sweden last week. That's a branch of the LTU (Luleå University of Technology) where students learn the arts of film-making and game-development. The game guys use the Nebula "spelmotorn" (what a wonderful word for "game engine") for their projects for quite a while now, and invited me to talk about the engine and the challenges of making Drakensang. It was more of a project management talk and very light on the technical side, but since actual programmers were in the minority I think that was a good decision instead of going straight into hardcore tech stuff.&lt;br /&gt;&lt;br /&gt;I wish I had a little more time to explore the town and its surroundings. Skellefteå (pronounced roughly like Shealleaf-tyo with emphasis on the 2nd syllable as I learned) is a relatively small town about 25 Swedish miles (1 mile is 10 km in Sweden!) south of the Arctic Circle, and as you can guess, it's still deep winter there. I was lucky to catch a nice sunny day, but the temperature was still only around -10 degree Celsius with about 1 meter of snow and a thick ice layer on the &lt;a href="http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=Skellefte%C3%A5,+Sweden&amp;amp;sll=37.0625,-95.677068&amp;amp;sspn=37.598824,79.013672&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=Skellefte%C3%A5,+V%C3%A4sterbotten,+Sweden&amp;amp;t=h&amp;amp;layer=c&amp;amp;cbll=64.746985,20.959679&amp;amp;panoid=lE9teVGV0kW_IO5KgY-1gw&amp;amp;cbp=12,277.07,,0,4.9&amp;amp;ll=64.746969,20.961142&amp;amp;spn=0.004486,0.038581&amp;amp;z=15"&gt;river which flows through the town&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The town of &lt;a href="http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=Skelleftea&amp;amp;sll=64.839597,22.598877&amp;amp;sspn=2.52745,9.876709&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=Skellefte%C3%A5,+V%C3%A4sterbotten,+Sweden&amp;amp;ll=65.07213,23.818359&amp;amp;spn=10.062953,39.506836&amp;amp;t=h&amp;amp;z=5"&gt;Skellefteå&lt;/a&gt; is really beautiful, with an orderly rectangular layout (so it's basically impossible to get lost). A surprising number of hotels, stores and restaurants are gathering around the town center, and there are &lt;a href="http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=Skellefte%C3%A5,+Sweden&amp;amp;sll=37.0625,-95.677068&amp;amp;sspn=37.598824,79.013672&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=Skellefte%C3%A5,+V%C3%A4sterbotten,+Sweden&amp;amp;t=h&amp;amp;layer=c&amp;amp;cbll=64.754805,20.937537&amp;amp;panoid=B7wiraPT7re1Iu2eagLM_g&amp;amp;cbp=12,251.7,,0,-4.01&amp;amp;ll=64.754804,20.937538&amp;amp;spn=0.004484,0.038581&amp;amp;z=15"&gt;colorful wood-planked town houses &lt;/a&gt;in the surroundings.&lt;br /&gt;A small airport about 20 km south of town seems to take the role of the railway station. I was surprised to find myself in a packed-full &lt;a href="http://en.wikipedia.org/wiki/Boeing_737"&gt;Boeing 737&lt;/a&gt; from Stockholm to Skellefteå (for some reason I was expecting &lt;a href="http://de.wikipedia.org/w/index.php?title=Datei:Douglas_DC-3,_SE-CFP.jpg"&gt;something like this&lt;/a&gt; ;), when the flight from Berlin to Copenhagen (and back) was only handled by a mere &lt;a href="http://en.wikipedia.org/wiki/CRJ900"&gt;Canadair CRJ900&lt;/a&gt; (which - unfortunately - was packed with overweight German businessmen).&lt;br /&gt;&lt;br /&gt;There's one thing I really like about Swedish people: they don't seem to like pointless small-talk. My seat neighbors on the plane didn't want to know where I come from and where I go to, what I want there, whether I like cats more then dogs or how the German beer is compared to their local beer. The atmosphere on the plane was quiet and relaxed, and I think I never encountered such a disciplined and friendly unboarding of a full plane as on the arrival at Skellefteå. Yet if you're asking for directions, they're friendly and helpful as if they know you for years.&lt;br /&gt;&lt;br /&gt;Oh Glorious Sweden :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-8631878902381880007?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/8631878902381880007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=8631878902381880007' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8631878902381880007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8631878902381880007'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2010/03/its-not-so-grim-up-north.html' title='It&apos;s Not So Grim Up North'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4921389983319094600</id><published>2010-01-30T18:37:00.004+01:00</published><updated>2010-01-30T19:42:35.977+01:00</updated><title type='text'>The Dark Side</title><content type='html'>Yeah, so I finally defected to the Dark Side and got myself a 13.3" MacBook Pro. Now that N3 runs on all 3 console platforms I'd like to explore the iPhone/iPod/iPad platform a bit. And iPhone development is only possible from the Mac, so the MacBook actually serves as some sort of hardware dongle.&lt;br /&gt;&lt;br /&gt;Overall, the MacBook is a great device. It (still) looks slick, has a great display, and is relatively light weight. I considered the MacBook Air, but finally went for the Pro, because it had twice as much hard disc space and RAM, but was still cheaper then the Air. And since I also want to run Windows on the machine, hard disc space is precious.&lt;br /&gt;&lt;br /&gt;The keyboard sucks ass though. I don't like those ultra-cheap ZX Spectrum keyboards which become more and more common on laptops. And the most important key, the Return key, is the smallest and easiest to miss. WTF?&lt;br /&gt;&lt;br /&gt;Surprisingly, I'm not a big fan of the user interface. I've only used the machine for a day or so, and while the UI certainly looks slick, I had a quite a few WTF moments. The most puzzling thing is that I have no idea where to find an application after it's installed. The XCode installer for instance simply finished and I was left wondering how to find and start the damned thing. It's not in the dock, and its not under Applications. Turns out its "somewhere" on the hard disc under the /Developer directory. I was looking for something like TortoiseSVN, found a Finder plugin, and pretty much failed to install it. The read-me file told me to find some files and manually drag them somewhere onto the Finder tool bar, and to drag something else somewhere else to start it automatically after login. However, those files where nowhere to be found after the installer was done. Why doesn't the installer take care of all that crap? I'm pretty sure I could have fixed it after investing some more time, but something like this shouldn't happen these days. I'll see how the Subversion integration in XCode works.&lt;br /&gt;&lt;br /&gt;I haven't found something like Live Writer to create blog posts (only some commercial apps, come on paying money for a blog editor? A good blog editor should come free with the OS like a web browser or a mail program).&lt;br /&gt;&lt;br /&gt;I tried Safari and I was shocked to see the web pages I usually visit cluttered with blinking ad banners. Not Safari's fault of course, but the next thing I did was installing Firefox with AdBlock Plus.&lt;br /&gt;&lt;br /&gt;I've dabbled around with MacOS from time to time during the 90s a bit, and at that time, usability was so much better compared to Windows. Today, I'm not so sure which one is better. Of course I've learned to get used to Window's quirks over the years, but I was honestly expecting myself to say something like "yeah, that's how its done" after playing around with OSX. But I didn't. Things are different, but not better. I'm still extremely excited to dive into Mac and iPhone development though :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4921389983319094600?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4921389983319094600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4921389983319094600' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4921389983319094600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4921389983319094600'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2010/01/dark-side.html' title='The Dark Side'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2843688925526575611</id><published>2009-11-10T13:19:00.001+01:00</published><updated>2009-11-10T13:21:36.675+01:00</updated><title type='text'>Drakensang River Of Time - Personal Edition</title><content type='html'>&lt;p&gt;Check this out: &lt;a href="http://www.amazon.de/amflussderzeit" target="_blank"&gt;www.amazon.de/amflussderzeit&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Amazon starts pre-ordering for the super-limited German *personalized edition* of “&lt;em&gt;Drakensang - River Of Time”&lt;/em&gt; with your own name on the box. First time any game offers this, as far as we’re aware at least. I really, really dig the DVD box cover by the way. We got some of those posters a few days ago and they’re simply admirable :o)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2843688925526575611?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2843688925526575611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2843688925526575611' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2843688925526575611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2843688925526575611'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/11/drakensang-rot-personal-edition.html' title='Drakensang River Of Time - Personal Edition'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3247929137230012250</id><published>2009-11-05T12:00:00.001+01:00</published><updated>2009-11-05T12:00:04.463+01:00</updated><title type='text'>Nebula3 SDK Nov 2009 Changelog</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;Here’s the new N3 SDK: &lt;a href="http://213.191.63.156/n3_sdks/N3SDK_Nov2009.exe" target="_blank"&gt;download link&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;As always, this only includes the sources for the Win32 platform. Console platform specific source code (Xbox360, PS3 and Wii) is not included for obvious legal reasons.&lt;/p&gt;  &lt;p&gt;Here’s a rough change log since the Apr2009 SDK:&lt;/p&gt;  &lt;h2&gt;&amp;#160;&lt;/h2&gt;  &lt;h2&gt;== Major New Features&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;unified XNAMath support on Win32 and Xbox360 platforms &lt;/li&gt;    &lt;li&gt;PS3 support (not part of public SDK, but lots of fixes for GCC 4.x in platform-agnostic code) &lt;/li&gt;    &lt;li&gt;HTTP filesystem wrapper now working properly, this allows to create standalone N3 apps which load all their data from an HTTP server (see testhttpviewer.exe for an example) &lt;/li&gt;    &lt;li&gt;“binary XML” support for much faster loading of big XML files (circumvents TinyXML) &lt;/li&gt;    &lt;li&gt;new “FrameSync” system for running main and render thread in lock-step &lt;/li&gt;    &lt;li&gt;new “Jobs” system to implement parallel jobs (CPU-thread-pool on Win32 and Xbox360, SPUs on PS3) &lt;/li&gt;    &lt;li&gt;window parenting, it’s now possible to open the render window as a child of another window, this makes it possible to embed N3 into another Windows application &lt;/li&gt;    &lt;li&gt;FMOD integration&amp;#160; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;== Foundation Layer&lt;/h2&gt;  &lt;h3&gt;Core&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;new Debug::StringAtomPageHandler to inspect string atom table from web browser &lt;/li&gt;    &lt;li&gt;type casting methods optimized in Ptr&amp;lt;&amp;gt; &lt;/li&gt;    &lt;li&gt;optional allocation from memory pool support for RefCounted objects (currently unstable!) &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Util&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Win32StringConverter: helper class to convert between UTF-8 and wide character string (currently only on Win32 platform) &lt;/li&gt;    &lt;li&gt;Util::Array::InsertSorted() now returns index of inserted element &lt;/li&gt;    &lt;li&gt;new Util::BitField&amp;lt;&amp;gt; class to allow bit mask operations on masks wider then 32 bits &lt;/li&gt;    &lt;li&gt;removed classes of old string atom system: Util::Atom&amp;lt;&amp;gt;, Util::Proxy&amp;lt;&amp;gt; &lt;/li&gt;    &lt;li&gt;new method Util::FixedArray&amp;lt;&amp;gt;::Resize() &lt;/li&gt;    &lt;li&gt;classes for new string atom system: Util::StringAtom, Util::StringBuffer, Util::LocalStringAtomTable, Util::GlobalStringAtomTable &lt;/li&gt;    &lt;li&gt;new method Util::Queue&amp;lt;&amp;gt;::Reserve() &lt;/li&gt;    &lt;li&gt;new direct access methods in Util::RingBuffer&amp;lt;&amp;gt; &lt;/li&gt;    &lt;li&gt;new method Util::Round::RoundUp() &lt;/li&gt;    &lt;li&gt;new class Util::SparseTable, for 2D data tables with a lot of empty cells &lt;/li&gt;    &lt;li&gt;Util::String:      &lt;ul&gt;       &lt;li&gt;new method CopyToBuffer() &lt;/li&gt;        &lt;li&gt;new optimized versions of Tokenize() which fills a provided string array with the tokens, allows to reuse an existing array object &lt;/li&gt;        &lt;li&gt;new static wrapper methods: IsDigit(), IsAlpha(), IsAlNum(), IsLower(), IsUpper(), StrCmp(), StrLen(), StrChr() &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;new util functions to help with “type punning” &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h3&gt;IO&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;BXmlReader: stream reader for “binary XML files” (created by the new binaryxmlconverter3.exe utility) &lt;/li&gt;    &lt;li&gt;some low-level-optimizations in ZIP filesystem wrapper &lt;/li&gt;    &lt;li&gt;application root directory stuff moved from AssetRegistry into Core::CoreServer &lt;/li&gt;    &lt;li&gt;new class GameContentServer, used to properly setup game data on some console platforms &lt;/li&gt;    &lt;li&gt;added support for http: and httpnz: schemes for reading data from HTTP servers through the N3 filesystem wrapper &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Math&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Xbox360 and Win32 math classes have been unified into XNAMath classes &lt;/li&gt;    &lt;li&gt;low-level performance tweaking &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Memory&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;experimental memory pool support on Win32 platform &lt;/li&gt;    &lt;li&gt;on Win32 platform, dynamically allocated memory is now 16-byte aligned (NOTE: there seems to be a hard to reproduce critical bug in Realloc() where HeapSize() returns a wrong value) &lt;/li&gt;    &lt;li&gt;new HTML debug output in Debug::MemoryPageHandler for memory pools &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Threading&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Threading::CriticalSection rewritten with &amp;quot;Fast critical sections with timeout&amp;quot; by Vladislav Gelfer (on Win32 platform) &lt;/li&gt;    &lt;li&gt;Threading::Event now supports “manual reset” behaviour &lt;/li&gt;    &lt;li&gt;Threading::Interlocked class now uses compiler intrinsics on Win32 and Xbox360 platform &lt;/li&gt;    &lt;li&gt;new class Threading::ThreadBarrier: stops a thread until all other threads have arrived at the barrier &lt;/li&gt;    &lt;li&gt;optimizations in Threading::SafeQueue &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;System&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;new class System::Win32Environment to access environment variables (Win32 platform only) &lt;/li&gt;    &lt;li&gt;Win32Registry class now reads registry key values as wide char and converts them to UTF-8 &lt;/li&gt;    &lt;li&gt;type punning fixes in System::ByteOrder &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Timing&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;removed MasterTime/SlaveTime system, global timing is now provided by the FrameSync subsystem &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Messaging&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;the Message::SetHandled() method was not thread-safe, now uses Interlocked::Exchange() to update its status &lt;/li&gt;    &lt;li&gt;Messaging::AsyncPort rewritten to allow better control over message handling behaviour through subclasses of HandlerThreadBase &lt;/li&gt;    &lt;li&gt;new async message handler thread classes BlockingHandlerThread, RunThroughHandlerThread &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Net&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;some type punning fixes in debugpacket.cc &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Http&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;new classes HttpClientRegistry, HttpStream, HttpNzStream to implement a transparent HTTP filesystem, the HttpNzStream uses client-side zlib decompression to improve download performance &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h3&gt;Debug&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;no noteworthy changes &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;App&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;new application identifier strings AppTitle and AppID, this is necessary for some console platforms &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Jobs&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;this is a new subsystem to distribute tasks either across threads in a thread-pool (Win32 and Xbox360) or the SPUs on the PS3 &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h3&gt;FrameSync&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;this is a new subsystem which implements better synchronization between the game thread and render thread &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;== Render Layer&lt;/h2&gt;  &lt;h3&gt;CoreGraphics&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;parent window stuff in DisplayDevice (Win32 platform) &lt;/li&gt;    &lt;li&gt;it’s now possible to share depth/stencil buffers between render targets &lt;/li&gt;    &lt;li&gt;the ShaderServer now parses a dictionary file (created by the shaderbatcher3.exe tool) instead of listing the directory content of the shaders directory &lt;/li&gt;    &lt;li&gt;removed array support from shader variables (shader parameter arrays are not very portable) &lt;/li&gt;    &lt;li&gt;some restructuring because of the PS3 port (some classes have been split into a base class and platform specific derived classes) &lt;/li&gt;    &lt;li&gt;new private method in D3D9RenderDevice: SyncGPU() this is called inside Present() to prevent the GPU from running too far ahead of the CPU (this is a driver-internal “optimization” which can lead to frame stuttering under some circumstances) &lt;/li&gt;    &lt;li&gt;better control over clearing a render target through clear flags &lt;/li&gt;    &lt;li&gt;the RenderDevice::SaveScreenshot() method is now responsible to set the MIME type on the output stream, this is because the actually saved MIME type may now be different then the requested type &lt;/li&gt;    &lt;li&gt;no more byte-order conversion when loading mesh files, this happens in the asset pipeline now &lt;/li&gt;    &lt;li&gt;new class MemoryMeshLoader, setup a mesh object from an existing VertexBuffer and IndexBuffer object &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;CoreAudio and Audio&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;the CoreAudio and Audio subsystem are obsolete and have been replaced with the FMOD-based Audio2 subsystem, which “automatically” works across all platforms, please check the FMOD license restrictions for commercial projects! &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;CoreAnimation&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;the following classes have been removed from CoreAnimation: AnimDrivenMotionSampler, AnimMixer, AnimSampler &lt;/li&gt;    &lt;li&gt;new file format for animation data: nax3 &lt;/li&gt;    &lt;li&gt;new animation curve type: Velocity, this is used by the AnimDrivenMotion feature &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Input&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;no noteworthy changes &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Frame&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;minor changes for Pre-Lightpass-Rendering &lt;/li&gt;    &lt;li&gt;better control over render target clear in FramePass &lt;/li&gt;    &lt;li&gt;FramePostEffect: rendering a full-screen-quad has been moved into new helper class RenderUtil::DrawFullScreenQuad &lt;/li&gt;    &lt;li&gt;frame shaders are now loaded on demand &lt;/li&gt;    &lt;li&gt;new LightServer class: LightPrePassServer implements light pre-pass rendering (a variation on deferred shading, currently only implemented in the PS3 port) &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Animation&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;anim evaluation has been “jobified” &lt;/li&gt;    &lt;li&gt;no more AnimDrivenMotion specific code in Animation subsystem (this is now handled through a new anim curve type which contains velocity keys) &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Audio2&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;new FMOD-based multiplatform audio subsystem &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Characters&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;skeleton evaluation has been “jobified” &lt;/li&gt;    &lt;li&gt;on PS3, skinning is now running on SPUs &lt;/li&gt;    &lt;li&gt;the entire character subsystem has been optimized (essentially rewritten) &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;InternalGraphics&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;uses the FrameSync subsystem to run render thread and game thread in lock-step (this basically fixes all stuttering problems) &lt;/li&gt;    &lt;li&gt;more debug infos displayed in web browser through GraphicsPageHandler &lt;/li&gt;    &lt;li&gt;lots of fixes to the attachment system (character joint attachments: swords, shields, etc…) &lt;/li&gt;    &lt;li&gt;restructured the Update/Render-Loop for better parallelization support, the idea is basically to make more room between updating an object and rendering an object so that asynchronous jobs have a better chance to finish on time before rendering requires the jobs output data &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Graphics&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;some new messages to communicate from the main thread to the render thread (see graphicshandler.cc) &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Models&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;nothing noteworthy… &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Particles&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;some restructuring for better portability &lt;/li&gt;    &lt;li&gt;particle updates have been “jobified” &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;RenderModules&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;no noteworthy changes… &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;RenderUtil&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;new helper class RenderFullScreenQuad &lt;/li&gt;    &lt;li&gt;new helper class NodeLookupUtil to lookup a ModelNodeInstance in a hierarchy &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Resources&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;nothing noteworthy &lt;/li&gt;    &lt;li&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;== Moved into Addons:&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;fx &lt;/li&gt;    &lt;li&gt;network &lt;/li&gt;    &lt;li&gt;locale &lt;/li&gt;    &lt;li&gt;posteffect &lt;/li&gt;    &lt;li&gt;ui &lt;/li&gt;    &lt;li&gt;vegetation &lt;/li&gt;    &lt;li&gt;vibration &lt;/li&gt;    &lt;li&gt;video &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;== New Stuff in ExtLibs:&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;FMOD &lt;/li&gt;    &lt;li&gt;RakNet &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3247929137230012250?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3247929137230012250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3247929137230012250' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3247929137230012250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3247929137230012250'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/11/nebula3-sdk-nov-2009-changelog.html' title='Nebula3 SDK Nov 2009 Changelog'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9071889257501173658</id><published>2009-10-23T17:57:00.001+01:00</published><updated>2009-10-23T17:57:50.470+01:00</updated><title type='text'>Drakensang River Of Time Intro</title><content type='html'>&lt;p&gt;Here’s the intro video of our new Drakensang game (River Of Time):&lt;/p&gt;  &lt;div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:c9b5cdb3-839a-4637-aebd-2c35b3f85514" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;div&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/HBcymMAthtU&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/HBcymMAthtU&amp;amp;hl=en" type="application/x-shockwave-flash" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=HBcymMAthtU" target="_blank"&gt;(Go here for the bigger version)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The cutscene has been created in-engine with our new &lt;a href="http://flohofwoe.blogspot.com/2009/10/tools-of-trade.html" target="_blank"&gt;cutscene editor tool described in one of my former blog posts&lt;/a&gt;, and then captured frame by frame and encoded with &lt;a href="http://www.radgametools.com/bnkmain.htm" target="_blank"&gt;Bink&lt;/a&gt; at 1280x720 (the YouTube version unfortunately looks quite a bit darker then the original if I’m not mistaken). The characters have higher resolution meshes and textures created especially for the intro video, but the underlying joint skeleton and facial animation system is identical with the ingame-characters. The decision to encode the cutscene into a video stream instead of running it in real-time was done early in the project to remove a few risks. We couldn’t be sure what the performance would look like with the high-res assets and all the dynamic lighting, and whether or not a lot of post-processing would be necessary after capturing the raw frames. Turns out that the real-time cutscene looks so good that no “cheating” was necessary, so in future projects we will probably do everything in real-time from the beginning.&lt;/p&gt;  &lt;p&gt;The advantage of building and tweaking the cutscene with an instant real-time preview can’t be stressed enough. The intro to the original Drakensang was done the traditional way, short scenes have been built in Maya, rendered over night, and then arranged and cut in some video editing tool. The massive turn-around time between tweaking something and seeing the result was a huge problem and in the end we ran out of time. Creating the new intro video was completely painless and straight-forward. The artists actually had fun creating it (at least that’s the impression I got watching them from time to time hehe), and I think that’s clearly visible in the result :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9071889257501173658?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9071889257501173658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9071889257501173658' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9071889257501173658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9071889257501173658'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/10/drakensang-river-of-time-intro.html' title='Drakensang River Of Time Intro'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6882480139813818605</id><published>2009-10-10T14:42:00.001+01:00</published><updated>2009-10-10T14:42:40.977+01:00</updated><title type='text'>Ninja Gaiden Sigma 2</title><content type='html'>&lt;p&gt;I’ve played halfway through the campaign of NGS2 yesterday evening, with mixed emotions. It’s very obvious that the director of this game has a very different vision of Ninja Gaiden then Itagaki. Sometimes for the better, but most of the times I would not call the changes actual improvements. It’s surprising how many gameplay elements which worked well have been removed. I hope that some of the shortcomings will be fixed in the higher difficulty levels (I’m currently playing on Warrior difficulty).&lt;/p&gt;  &lt;h5&gt;The Good:&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Graphics have improved dramatically!&lt;/strong&gt; The game generally looks a lot crisper (I guess that NG2 was upscaled, and NS2S is native 720p), textures seems to be higher resolution, normal mapping and specular highlight effects have been tuned, it’s really a difference like night and day (in some cases literally, when returning to the Ninja village in chapter 2 it is now broad daylight, not night time). This is what the original NG2 should have looked like.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;New minions:&lt;/strong&gt; There are a couple of new enemies in the game, some variations of NG2 minions, and some variations of original Ninja Gaiden monsters.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;New and tweaked bosses: &lt;/strong&gt;There are a couple of new boss fights in the game which are variations of the final boss in the original NG2. The Genshi fights are more interesting (you can now do an Izuna Drop on Genshi for instance).&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Excessive rocket spam removed:&lt;/strong&gt; that’s about the only good gameplay change, almost all of the “unfair” rocket spam has been removed.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Mission Mode now included in the game, plus Coop: &lt;/strong&gt;Since the original NG2 wasn’t released in Germany, there’s also no downloadable content on the Xbox Live marketplace (damn you Microsoft). NG2S includes a mission mode, and adds 2-player-coop to those missions.&lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;The Bad:&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Much fewer enemies on screen: &lt;/strong&gt;this is most painful change. The oh-shit-moments of NG2 when 15 blood-thirsty spider-clan-ninjas where rushing down a hallway, running into Ryu which is starting an Ultimate Technique, turning the whole screen into a mess of flying body parts, and then cleaning up the survivors with a series of Obliteration moves. That’s no longer happening in NG2S. Typically, there are no more then 3 or 4 enemies on screen. Generally, combat encounters are much shorter and easier then in NG2.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Slowdown, tearing and in-level loading still there:&lt;/strong&gt; The dreaded slowdown from NG2 still happens, it’s not happening so often as in NG2, but only because the number of enemies on screen and rocket spam has been reduced. When the slowdown happens it even kicks in sooner, with less on-screen action, then in the original NG2. This is a big let-down. There are places with screen-tearing even when there are no enemies on screen, and the game still pauses mid-game to load data. It’s not game-breaking but disappointing considering that the team had over a year to tweak and optimize.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Empty hallways: &lt;/strong&gt;A lot of combat encounters have been removed from the game, locations which were packed with enemies in the original are desolate in NGS2. I really hope this is just a difficulty level thing, and that there are more encounters in the higher difficulty levels.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Fewer choices: &lt;/strong&gt;some of the design decisions are downright stupid:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Weapon upgrades are now limited to a few shops, and the first time any weapon can be upgraded to level 3 is very late in the game (at the start of the Moscow chapter). Weapon upgrades don’t cost any money now however, sounds good at first, but money and shops in general quite useless now (at least in Warrior difficulty).&lt;/li&gt;      &lt;li&gt;Life Of The Thousand Gods is now immediately activated when picked up, and no longer refills the life bar. This removes a very nice tactical elements from the game (should I use the immediate benefit of having a longer life bar, or should I use it as an additional health potion during the next boss fight)?&lt;/li&gt;      &lt;li&gt;Same with the Life Of The Gods items, it’s no longer possible to manually activate them when needed, instead they auto-activate when picked up.&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;h5&gt;The Rest:&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;I actually like the new blood-effect-replacement and toned down violence, it makes the game more arcady and more enjoyable (IMHO).&lt;/li&gt;    &lt;li&gt;One really starts to appreciate how good the 360’s controller is after 5 or 6 hours of playing with the PS3 controller. My left hand literally hurt after the session.&lt;/li&gt;    &lt;li&gt;The additional campaign chapters with the new playable characters are disappointing. It’s too little to feel comfortable with the new characters and their moves, they’re limited to a single weapon, and the levels are mostly reused from the original game.&lt;/li&gt;    &lt;li&gt;They actually tried to fix the story LOL. There’s a “prelude comic” during installation and a few fixes to the cut-scenes during the game to make the story more comprehensible and give it more of a background… as if anybody gives a shit about the story in a Ninja Gaiden game. The result is a complete mess. I can imagine a game featuring ninjas where story actually plays an important part, but not in the Ninja Gaiden universe. It’s really too late for that hehe. The only thing that’s really missing in Ninja Gaiden are pirates, oh … and zombies of course.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If NGS2 is an indication of what the future of Ninja Gaiden looks like without Itagaki then I’m out. The game looks shiny, but the changes to the core game-play are all aiming into the wrong direction for my taste. I was hoping that NGS2 becomes what Ninja Gaiden Black was to the original, a real improvement to an already great game, and if there’s any game which really needs a good polish, it is the original NG2. But NGS2 adds only very few improvements, and abandons too many good ideas from its predecessor. It’s just different, not better then NG2.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6882480139813818605?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6882480139813818605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6882480139813818605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6882480139813818605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6882480139813818605'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/10/ninja-gaiden-sigma-2.html' title='Ninja Gaiden Sigma 2'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7135664494131187506</id><published>2009-10-06T18:09:00.001+01:00</published><updated>2009-10-06T18:09:10.210+01:00</updated><title type='text'>Tools of the Trade</title><content type='html'>&lt;p&gt;We have ramped up tools development at Radon Labs considerably during the development of the two Drakensang games. Traditionally we have been (and still are) a bit conservative about inhouse tool development and try to avoid re-inventing wheels as much as possible. Each new custom-tool requires permanent maintenance work and if a “standard industry tool” exists for a job it is usually better to just use this. But especially in the domain of “game-logic stuff” there are basically no standard tools, so the situation is much more dire compared to graphics or audio tools. &lt;/p&gt;  &lt;p&gt;We have traditionally been using Excel tables and XML files compiled into an SQLite database for “game data”. This works pretty well if the number of “work items” is around a few hundred. But for complex RPG games, the number of work items is in the range of tens-of-thousands (quest tasks, dialog takes, voice over snippets, graphics objects, textures, items, NPCs, monsters, behaviour scripts, and so on…). Excel tables and raw XML files don’t scale up very well because they lack game-specific features for filtering, searching, statistics, and of course the possibility of human error is very high, and finding and fixing those errors isn’t much fun either. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Texture Tool&lt;/h3&gt;  &lt;p&gt;The very first custom tool in C# (to try the waters so to say) was a simple replacement for an Excel table which defined texture attributes (stuff like the size and DXT format of a texture, mip-map quality and so on). The Excel table allowed to give each individual texture its own set of attributes. For a small project with a few hundred textures this works pretty well. Drakensang has around 15,000 textures however, and this is way beyond the territory where Excel is starting to become a pain in the ass. Thus we wrote this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_cWdorEDEaNg/Sst5le21PKI/AAAAAAAAAIE/YAW7kUhuppE/s1600-h/texture_tool%5B11%5D.jpg"&gt;&lt;img title="texture_tool" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="442" alt="texture_tool" src="http://lh3.ggpht.com/_cWdorEDEaNg/Sst5l4E0x6I/AAAAAAAAAII/hW_0RieEFhU/texture_tool_thumb%5B9%5D.jpg?imgmax=800" width="807" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The tool manages the same information as the Excel table it replaces, but has much better filtering and manipulation features. The left hand sides gives a tree-view of all texture categories, and it’s possible to either display all textures, or textures of a given category, and it’s also possible to further filter the textures by a pattern (for instance to display all normal textures of the “armor” category, click on “armor” in the tree view and type “*_bump.*” into the top most line of the “File” column. Entering a value into one of the other top-most column-entries will set this attribute value to all displayed textures. It’s a very simple tool, but it’s easy to use and scales up very well to tens-of-thousands of textures while still making it possible to find and tweak a single attribute of a specific texture with ease.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Story Editor&lt;/h3&gt;  &lt;p&gt;When we started planning Drakensang, we knew that we would need new tools for creating quests, dialogs and game logic scripting. On the surface, these 3 things are something completely different, but for the game core, quests, dialogs and scripts aren’t that different (the common element is the use of Conditions (small C++ objects which check whether some condition in the game world is true) and Actions (similar C++ objects which manipulate the game world)). Thus the Story Editor was born (actually, it’s a Dialog/Quest/Script editor). The Story Editor loads and saves XML files, which are compiled into the game database during the build process, or directly from the tool to immediately check the results in the game. We couldn’t anticipate all required features for the story editor at the start of the project, thus the editor was constantly worked on during the development of Drakensang (we added a lot of features to improve localization, proof-reading or voice-over integration for instance).&lt;/p&gt;  &lt;p&gt;Note that the Story Editor currently suffers a bit from the typical “inhouse tool UI aesthetics problem” ;)&lt;/p&gt;  &lt;p&gt;Here’s a screenshot of the Story Editor when working on a simple quest:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/Sst5mfZbamI/AAAAAAAAAIM/p5oGR5bvaqA/s1600-h/story_editor_2%5B14%5D.jpg"&gt;&lt;img title="story_editor_2" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="417" alt="story_editor_2" src="http://lh4.ggpht.com/_cWdorEDEaNg/Sst5m0ixQHI/AAAAAAAAAIQ/YG3e4YlrYVk/story_editor_2_thumb%5B12%5D.jpg?imgmax=800" width="786" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On the left is the simple linear task list, the panels on the right show the attributes of the currently selected task (for instance the conditions and actions associated with the task).&lt;/p&gt;  &lt;p&gt;Here’s the screenshot of the Story Editor with a simple action script:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_cWdorEDEaNg/Sst5nHLDDHI/AAAAAAAAAIU/Fz6tNx-aMkw/s1600-h/story_editor_1%5B9%5D.jpg"&gt;&lt;img title="story_editor_1" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="526" alt="story_editor_1" src="http://lh5.ggpht.com/_cWdorEDEaNg/Sst5ntDbpSI/AAAAAAAAAIY/LFUB0TKz0mY/story_editor_1_thumb%5B7%5D.jpg?imgmax=800" width="791" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;We opted against a traditional scripting language, but instead used a “point and click” approach. A script is just a simple collection of Conditions and Actions. These could just as well be wrapped into LUA functions for instance. Our current approach is probably not as powerful as real scripting system, but definitely less error-prone and easier to control.&lt;/p&gt;  &lt;p&gt;Finally here’s the Story Editor when working on a dialog:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_cWdorEDEaNg/Sst5oEJCt8I/AAAAAAAAAIc/XsmXs8R6AEU/s1600-h/story_editor_0%5B4%5D.jpg"&gt;&lt;img title="story_editor_0" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="530" alt="story_editor_0" src="http://lh3.ggpht.com/_cWdorEDEaNg/Sst5oVMusdI/AAAAAAAAAIg/Wy3WY5y2PIc/story_editor_0_thumb%5B2%5D.jpg?imgmax=800" width="796" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Dialog takes can be associated with Conditions (to show or hide dialog takes based on some in-game condition), or Actions (to manipulate the game world as the result of a conversation). The Comment tab on the right side is most useful to add instructions for audio recording sessions.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Sequence Editor&lt;/h3&gt;  &lt;p&gt;In the first Drakensang, in-game cutscenes had been hand-scripted by defining a sequence of Actions in the Story Editor, basically in the most un-intuitive way imaginable. For the new Drakensang, we wrote a whole new “Sequence subsystem” along with a new tool (the Sequence Editor) which gives control over cutscenes back into the hand of the artists and provides a very intuitive workflow with instant turnaround times (resulting in a dramatic quality improvement if I may say so). Here’s a screenshot of the Sequence Editor in action on a dual-monitor setup:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/Sst5ox8xEeI/AAAAAAAAAIk/3GIYHWoIfKw/s1600-h/sequence_editor_0%5B5%5D.jpg"&gt;&lt;img title="sequence_editor_0" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="414" alt="sequence_editor_0" src="http://lh6.ggpht.com/_cWdorEDEaNg/Sst5pEJeGaI/AAAAAAAAAIo/ANRflp0m7-k/sequence_editor_0_thumb%5B3%5D.jpg?imgmax=800" width="1028" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On the left-hand side is the actual editor, on the right-hand side is the ingame-preview. Tool and game communicate through XML messages over a TCP/IP connection, changes in the tool immediately show up in the preview. The other direction works as well, for instance it is possible to set keys for the camera or objects directly in the preview window, complete with snap-to-ground and other time-savers.&lt;/p&gt;  &lt;p&gt;Here’s a more detailed shot of the Sequence Editor:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/Sst5pveum9I/AAAAAAAAAIs/Sxd3CA1T_wM/s1600-h/sequence_editor_1%5B6%5D.jpg"&gt;&lt;img title="sequence_editor_1" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="713" alt="sequence_editor_1" src="http://lh4.ggpht.com/_cWdorEDEaNg/Sst5qGNIP1I/AAAAAAAAAIw/br5aoBYjdx0/sequence_editor_1_thumb%5B4%5D.jpg?imgmax=800" width="915" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;“Trackbar Elements” from the bottom area (Play Sound, Depth Of Field, etc…) can be drag’n’dropped into the timeline area above. Every trackbar element comes with a number of attributes, most of them can be animated over time. Trackbar attributes are displayed in the right-side column (in the screenshot, I have selected an “Ambience Bubble” element which allows to manipulate the ingame lighting, posteffect parameters, and other stuff which is important to set the visual “mood” of a scene). Animated parameters are edited in the Graph Editor which looks and feels very similar to Maya’s graph editor window:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_cWdorEDEaNg/Sst5qXrMlUI/AAAAAAAAAI0/VqrDE7KEz6g/s1600-h/sequence_editor_2%5B6%5D.jpg"&gt;&lt;img title="sequence_editor_2" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="342" alt="sequence_editor_2" src="http://lh6.ggpht.com/_cWdorEDEaNg/Sst5qzjDB6I/AAAAAAAAAI4/e6Tmxp9sREQ/sequence_editor_2_thumb%5B4%5D.jpg?imgmax=800" width="707" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It’s important to note that complex character animations are not created in the Sequence Editor, instead the sequence system will usually only trigger existing character animations from the character’s animation library. How complex character animation tracks are is up to the cutscene designer. Sometimes its better to fire a lot of small, generic animations and do the path-animation in the Sequence Editor, sometimes it’s better to generate one big motion-capture animation for the entire cutscene, complete with the actual character movement.&lt;/p&gt;  &lt;p&gt;One very cool feature of the sequence system is its extensibility. Simple trackbar elements, like “Depth Of Field” or “Camera Shake” can be implemented in under an hour by extending an XML config file which describes the attributes of the new element to the editor tool, and by writing a very simple subclass in the engine which connects the animated values of the trackbar to another subsystem (for instance the PostEffects subsystem in case of the Depth Of Field trackbar).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Table Editor&lt;/h3&gt;  &lt;p&gt;The new Table Editor is aimed at finally replacing the Excel tables for game object template data. In Drakensang (or Mangalore in general) a game object’s persistent state is simply described by a collection of typed key/value-pair attributes. Different game object categories have different sets of attributes. For instance a Monster game object has a different attribute set then a Weapon game object.&lt;/p&gt;  &lt;p&gt;Traditionally, we had one Excel table per game object category, and one line in the table per game-object template. The value of some of the attributes (instance attributes) can be set in the Maya level editor to a different value for each game object instance.&lt;/p&gt;  &lt;p&gt;Some of the bigger game object tables became a really critical bottleneck during the production of Drakensang, since only one person could work at a table at a time. Also even though the tables were saved in XML format, both CVS and SVN are pretty much useless for merging.&lt;/p&gt;  &lt;p&gt;Thus the idea was born to move the game data tables into a true database backend, and then create one generic “Table Editor” and later on, several smaller, specialized Editor tools which basically provide a different view into the database. This is also the very first step of moving away from Maya as a level editor towards a &lt;a href="http://flohofwoe.blogspot.com/2007/10/ive-been-discussing-with-bernd-lot.html" target="_blank"&gt;truly collaborative level design environment&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Here’s a screenshot of the generic Table Editor tool:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_cWdorEDEaNg/Sst5rEMjsCI/AAAAAAAAAI8/lAe-C1BtNqY/s1600-h/db_frontend%5B29%5D.jpg"&gt;&lt;img title="db_frontend" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="588" alt="db_frontend" src="http://lh3.ggpht.com/_cWdorEDEaNg/Sst5rs_t1UI/AAAAAAAAAJA/xdjAbXt13SU/db_frontend_thumb%5B23%5D.jpg?imgmax=800" width="912" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On first glance, this just looks like a nifty Excel replacement, but under the hood it is much more:&lt;/p&gt;  &lt;p&gt;There’s a complete user system with login and access rights (in the screenshot above, I can see that I am currently logged in as “floh”, and that 1 other user is currently editing the Weapon-Table).&lt;/p&gt;  &lt;p&gt;Then there’s a complete revision control system. The table basically extends into the time dimension, and it’s possible to inspect the table at any point in the past. There’s also a very detailed change-log, which not only tells me who modified the table at what time, but also all the changes made to the table:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_cWdorEDEaNg/Sst5sA0PjqI/AAAAAAAAAJE/5GQOBKkluvo/s1600-h/db_editor_changelog%5B5%5D.jpg"&gt;&lt;img title="db_editor_changelog" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="442" alt="db_editor_changelog" src="http://lh5.ggpht.com/_cWdorEDEaNg/Sst5sclMsuI/AAAAAAAAAJI/o7gMzq0IIxM/db_editor_changelog_thumb%5B3%5D.jpg?imgmax=800" width="742" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Of course it’s also possible to revert the content of any cell to any point in time.&lt;/p&gt;  &lt;p&gt;When a level designer changes values in a table, it will only happen in a local sandbox (the changed values already live in the central database, but are marked as local data of the user). This allows a level designer to mess around with the tables without affecting the other users. When everything works as expected, the changes are committed into the “global domain” and the new values are visible to all.&lt;/p&gt;  &lt;p&gt;The generic database table editor tool is very powerful, but the whole system really shines with specialized front-end editors like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_cWdorEDEaNg/Sst5s-_2YUI/AAAAAAAAAJM/DX5BucAbvLU/s1600-h/db_special_frontend%5B4%5D.jpg"&gt;&lt;img title="db_special_frontend" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="552" alt="db_special_frontend" src="http://lh4.ggpht.com/_cWdorEDEaNg/Sst5tL5cRRI/AAAAAAAAAJQ/cJDlBP5MTmQ/db_special_frontend_thumb%5B2%5D.jpg?imgmax=800" width="845" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This is basically just a different frontend to the global game database with a specialized GUI for efficiently equipping characters and chests in the game. The general idea here is that such a specialized editor tool is written for tasks where working with the generic editor is not desirable because it would be too cumbersome, un-intuitive or error-prone.&lt;/p&gt;  &lt;p&gt;There’s also a lot of interesting work going on in our build-pipeline at the moment, but I’ll leave this to another post :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7135664494131187506?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7135664494131187506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7135664494131187506' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7135664494131187506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7135664494131187506'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/10/tools-of-trade.html' title='Tools of the Trade'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_cWdorEDEaNg/Sst5l4E0x6I/AAAAAAAAAII/hW_0RieEFhU/s72-c/texture_tool_thumb%5B9%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1049550500411919059</id><published>2009-09-13T14:43:00.001+01:00</published><updated>2009-09-13T15:22:03.808+01:00</updated><title type='text'>Workload</title><content type='html'>&lt;p&gt;I’ve been playing around with getting N3 up and running in a pure web environment, running without local installation, pulling all data from a web-server instead of the local hard-disc, embedding rendering into a web-browser and so on. Works pretty well so far, but I’m shocked how arcane and downright silly writing a plug-in for Internet Explorer is. I can’t believe MS hasn’t released a simplified, specialized plug-in API for IE by now, but instead one is still required to dive right into the disgusting cesspit that is ActiveX / OLE. I pity the poor souls who had to make a living in the 90’s grinding on code for OLE or CORBA. Compared to .NET today, this really was software development hell.&lt;/p&gt;  &lt;p&gt;On the other hand, NPAPI, the plug-in API for everything else then IE, also hails from the 90’s but it’s clear that it was designed by sane people, and to do one thing right instead of all things poorly: to let people write plug-ins for the Netscape browsers. Embedding N3 into Firefox was a matter of hours. But I already wasted 2 weekends even getting a clear idea how to do the same thing in IE, and every time I’ve finished another doc-reading-session I feel like I must wash my hands.&lt;/p&gt;  &lt;p&gt;Gaming! If not for XBLA I would have considered to give up console gaming in the past months and return into the PC camp. Game prices for the 360 and PS3 are simply hilarious right now in Germany. 70 is the new 60 for quite a while now (and 60 Euros was already the outrage when “next-gen” started). Combined with the fact that it feels like half of the games are not even released in Germany it really doesn’t make a lot of sense to own a 360 (or PS3). The new Games On Demand service on Xbox Live just makes things worse. Of course you only get the crappy German versions of games (remember, there’s a hard IP address region check on Xbox Live), and whoever thought that 30 Euros for a 3 year old launch game is a good idea clearly lost touch with reality.&lt;/p&gt;  &lt;p&gt;Thank god the UK exists, free haven and last stronghold of console gaming in Europe, where prices are reasonable and censorship doesn’t exist. England is probably saving the 360 in Germany right now. God Save The Queen :)&lt;/p&gt;  &lt;p&gt;But not all is bad in the console world. XBLA has reinvented itself during the summer. Games like Battlefield 1943, Trials HD, and Shadow Complex catapulted the service to a new quality and sales numbers level. IMHO, XBLA was in dire danger to become a dump for cheap-ass retro-titles, but since Battlefield everything has changed. I’ve had more fun with Shadow Complex then with Gears 1 and 2 combined. I hope the success of SC means Gears 3 will become a bit more interesting (of course I don’t want a side-scrolling Gears, but I’d like to see more exploration and maybe some character up-leveling).&lt;/p&gt;  &lt;p&gt;Dirt2 was a day-one for me, but at first I was terribly disappointed because I was expecting a somewhat arcady rally game like the original Dirt. Everything which I liked about Dirt was removed and more stuff was added which I clearly didn’t like. Especially the X-TREME bullshit: didn’t like the crap you’re co-pilot was spilling before the race (I’m Mister Smooth, you’re Mister Steady)? Well, now the game is completely full of this shit. I’m only halfway through Dirt2, so I’m not exactly sure, but they removed Pikes Peak (and hill-climbing all together), as well as all the amazing “pseudo real world” tracks in Europe, and replaced them with complete fantasy tracks in more X-TREME locations like China and Malaysia. I’ve been playing a bit of the original Dirt again, and the game still looks pretty darn good compared to Dirt2. The car models in Dirt2 are clearly better, the environment in Dirt2 is more detailed, but for some reason don’t look as “realistic” as in Dirt1. The European tracks in Dirt simply nailed the look of a dark German forest during a rainy day. Dirt2 looks a lot more like a typical&amp;#160; video game (Malaysia is a looker, though). Well, I still made my peace with Dirt2. It’s not a rally game, it’s a pure arcade racer now. It looks very good, it plays well, its fast paced, and it has a really good multiplayer mode. But the name Colin McRae does not belong any longer on Dirt2’s box.&lt;/p&gt;  &lt;p&gt;Now that the rally-genre is completely dead on the consoles I really wish Turn10 would step in and settle the issue once and for all. Give us Forza &lt;strong&gt;Rally&lt;/strong&gt;sport already. Forza’s driving model is too good for just one game :)&lt;/p&gt;  &lt;p&gt;I gave in to the hype and am currently about halfway through Arkham Asylum. My brain hasn’t been “indoctrinated” by American comics during my childhood. As a result I find that whole super-hero thing completely silly. I never enjoyed a single Marvel-licensed game (I think my record was like 20 minutes into one of the Spiderman games), and with few exceptions, all of the movies were utter crap (especially the Batman movies, haven’t seen the last one yet though). So… I was a bit skeptical about yet another super-hero game, to say the least. Well, what can I say? The game is fucking great! It’s a bit too old-school here and there (for instance, there’s A LOT of air duct crawling in the game). Sometimes I believe there’s only one guy in the gaming industry who’s doing all the air-ducts. He’s probably started his career in Half-Life, and then went on to Splinter Cell, Riddick, MGS and probably every other stealth-shooter ever made. So that’s a bit strange, crawling around in air ducts as The Batman. There are other strong design clichees at work in the game here and there. For some strange reason, some corridors in the Asylum look like they were stripped from a space-craft (you know, one of those typical video game space ship corridors, metallic surface, a bit rusty, hexagonal profile, leaky pipes along the walls). Maybe Mister Airducts brought his brother with him, who’s specialized in corridors.&lt;/p&gt;  &lt;p&gt;But that’s just nitpicking, and a true hardcore gamer feels right at home with all the air-ducts and spacecraft corridors… The game itself plays really, really well, especially the slick hand-to-hand combat. There’s a lot to explore, sneaking, planning, nosing around in dark corners, just my thing. At times the game feels like Bioshock, and at other times a bit like Splinter Cell, but all in all this is the best implementation of the Batman universe I have ever seen, better then the movies anyway :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1049550500411919059?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1049550500411919059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1049550500411919059' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1049550500411919059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1049550500411919059'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/09/workload.html' title='Workload'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5243793827934718490</id><published>2009-08-16T13:06:00.001+01:00</published><updated>2009-08-16T13:10:43.514+01:00</updated><title type='text'>XNAMath</title><content type='html'>&lt;p&gt;With all the focus on the console platforms I didn’t notice one very cool addition to the March DirectX SDK: XNAMath. This is basically the traditional Xbox360 vector math lib, ported to the PC with SSE2 and inlining support. The N3 math classes are now running from the same code base on top of XNAMath for the PC and Xbox360 platforms. Maik has spent a few days to analyze the generated code and after some tweaking the improvements for our simple math benchmarks are absolutely dramatic, up to 4x faster on the PC side!&lt;/p&gt;  &lt;p&gt;We had to change our memory allocation routines on the PC to always return 16-byte aligned memory, without this, XNAMath isn’t really useful since the aligned load/store functions can’t be used on vectors residing in heap buffers. Really strange that there isn’t a way to do this through the Win32 heap functions directly (or is there?).&lt;/p&gt;  &lt;p&gt;Other then that I’m currently deep into “jobifiying” the render thread, in order to free the PS3-PPU from the mundane number-crunching tasks. Properly jobified code will also “automatically” run about 2x faster on a 2-core PC, and about 3..4x faster on the Xbox360, since even single jobs will be split and processing will be distributed to worker threads. The actual speedup may even be higher, since the data must be re-organized into small independent chunks (“slices”) of about 16..32 kByte each in order to make the best use of the SPU local memory, and this improved spatial locality is also extremely beneficial for CPU caches on the other platforms (I think I’m starting to sound like a record, but I can’t stress enough how good this data-reorganization will be for N3 on ALL platforms :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5243793827934718490?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5243793827934718490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5243793827934718490' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5243793827934718490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5243793827934718490'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/08/xnamath.html' title='XNAMath'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9052618953065116555</id><published>2009-07-28T19:43:00.001+01:00</published><updated>2009-07-28T19:43:03.829+01:00</updated><title type='text'>Brain Rot</title><content type='html'>&lt;p&gt;I think working on the PS3 is slowly destroying my higher brain functions. All I can think of at the moment are cycle counts, cache misses, memory latency, compiler intrinsics and synchronization issues. It’s becoming harder and harder to communicate with humans, let alone formulate a proper blog post. On one hand I welcome this fallback into nerd-dom, reminds me of the time when I learned programming by hacking hex-code into the 256 bytes of RAM of the LC-80. On the other hand it’s incredibly frustrating because everything takes so fucking long. Working for 3 days on a small problem which doesn’t even exist on other platforms isn’t fun. But ultimately the PS3 port will be incredibly good for Nebula3 because it forces me to think very hard about the data layout and data flows in the engine, and the PS3-port is now laying the foundation to scale beyond 2..3 cores on all future platforms. &lt;/p&gt;  &lt;p&gt;So, quick status update before I turn into a zombie:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;We’ll support &lt;a href="http://www.fmod.org/" target="_blank"&gt;FMOD&lt;/a&gt; in the future, integration into Nebula3 is currently underway. Only sensible way to do sound in multiplatform projects IMHO.&lt;/li&gt;    &lt;li&gt;I have implemented Wolfgang Engel’s &lt;a href="http://diaryofagraphicsprogrammer.blogspot.com/2008/03/light-pre-pass-renderer.html" target="_blank"&gt;light pre-pass renderer&lt;/a&gt; in the PS3 port. I think we’ll use this also for the other platforms (well, except the Wii of course). Very cool stuff and solves a lot of problems on the fragment-shader level (jeez, I meant pixel-shader). I’ll write a bit more about this later.&lt;/li&gt;    &lt;li&gt;I’m currently implementing a job system for Nebula3, designed around PS3 SPURS jobs. On other platforms, jobs will run in a thread-pool on the CPU. It will not be completely multiplatform, but it will be easy to create and maintain jobs for multiplatform projects (the only thing not multiplatform will be the actual job function, but this is usually just a few (maybe a few dozen) lines of code). Once I have profiling results I’ll write a blog post about the design and usage of the job system (it’s a bit different then what I described &lt;a href="http://flohofwoe.blogspot.com/2009/02/eva.html" target="_blank"&gt;here&lt;/a&gt;).&lt;/li&gt;    &lt;li&gt;The multiplayer component of N3 is currently being rewritten and ported to Xbox360 (and later PS3). The PC version (and probably PS3 version too) is based on RakNet, on the 360 we’re using an API from the XDK.&lt;/li&gt;    &lt;li&gt;I have completely rewritten the whole StringAtom system for performance and memory footprint and have dropped the generalized Atom&amp;lt;&amp;gt; and Proxy&amp;lt;&amp;gt; classes (which the old StringAtom system was built on). The new system is hardwired for strings and nothing else.&lt;/li&gt;    &lt;li&gt;Call Of Juarez BiB totally caught me by surprise. Best game so far this year on the 360 IMHO, and much more streamlined then the original.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That’s all for now. It will be very good to eventually crawl out of the cave into the sunlight and develop back into a normal human being again :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9052618953065116555?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9052618953065116555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9052618953065116555' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9052618953065116555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9052618953065116555'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/07/brain-rot.html' title='Brain Rot'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7358572368078480318</id><published>2009-06-27T13:06:00.001+01:00</published><updated>2009-06-27T13:47:55.118+01:00</updated><title type='text'>A more streamlined shader system</title><content type='html'>&lt;p&gt;I’m currently porting N3’s shader system to the PS3, and while I got it basically working, I’m not satisfied because it’s not really possible to come up with a solution that’s really optimized for the PS3 without creating my own version of the DirectX FX system. Currently N3 depends too much on obscure FX features which actually aren’t really necessary for a realtime 3D engine. So this is a good time to think about trimming off a lot of fat from the shader classes in CoreGraphics. &lt;/p&gt;  &lt;p&gt;I think the higher level state management parts are in pretty good shape. The FrameShader system divides a render-frame into render-passes, posteffect-passes and render-batches, draw-calls are grouped by shader-instance. All together these do a good job of preventing redundant state switches. So above the CoreGraphics subsystem (almost) everything is fine.&lt;/p&gt;  &lt;p&gt;Here’s how shaders are currently used in N3:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;FramePass: a pass-shader sets render states which are valid throughout the whole pass (for instance, a depth-pass may disable color-writes, and so on…), but doesn’t contain vertex- or pixel-shaders&lt;/li&gt;    &lt;li&gt;FrameBatch: this is one level below passes, a batch-shader sets render state which is valid for rendering a batch of ModelNodeInstances with the same ModelNodeType (for instance, a render batch which contains all SrcAlpha/InvSrcAlpha-blended objects would configure the alpha blending render states accordingly). FrameBatches usually don’t have a vertex/pixel-shader assigned, but there are cases where this is useful, if everything that is rendered during the batch uses the same shader anyway.&lt;/li&gt;    &lt;li&gt;PostEffects: a post-effect-pass uses a shader to render a fullscreen-quad&lt;/li&gt;    &lt;li&gt;StateNodes and StateNodeInstances: node-instances are always rendered in batches, so that material parameters only need to be set once at the start of a node-batch, other parameters (most notably the ModelViewProjection matrix) must be set before each draw-call.&lt;/li&gt;    &lt;li&gt;Specific subsystems may use shaders for their own rendering as they please, but let’s just say that those will have to live with the limitations of the new shader system ;)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This defines a pretty small set of requirements for a refactored Nebula3 shader system. By removing feature requirements and making the system *less* flexible, we have a better foundation for low-level optimizations and especially for porting the code to other platforms without compromises.&lt;/p&gt;  &lt;p&gt;Here’s a quick overview of the current shader system:&lt;/p&gt;  &lt;p&gt;The important classes and concepts to understand N3’s shader system are &lt;strong&gt;Shader&lt;/strong&gt;, &lt;strong&gt;ShaderInstance&lt;/strong&gt;, &lt;strong&gt;ShaderVariation &lt;/strong&gt;and &lt;strong&gt;ShaderVariable&lt;/strong&gt;. The basic idea of the shader system is to move all the slow stuff into the setup phase (for instance looking up shader variables) instead of doing it every frame.&lt;/p&gt;  &lt;p&gt;A &lt;strong&gt;Shader&lt;/strong&gt; encapsulates an actual shader file loaded from disc. Shaders are created once at application start, one Shader object per shader file in the shd: directory. Shaders are not actually used for anything except providing a template for ShaderInstances.&lt;/p&gt;  &lt;p&gt;A &lt;strong&gt;ShaderInstance&lt;/strong&gt; is created from a specific shader and contains its own set of shader parameter values. For instance, every Models::StateNode object creates its own ShaderInstance and initializes it with its specific material parameters.&lt;/p&gt;  &lt;p&gt;A &lt;strong&gt;ShaderVariable &lt;/strong&gt;is created from a ShaderInstance and is used to set the value of a specific shader parameter of the ShaderInstance.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;ShaderVariations &lt;/strong&gt;are the most interesting part of the system. Under the hood, a ShaderVariation is an FX Technique, and thus can have a completely different set of render states and vertex/pixel shader code. The variation that is currently used for rendering is selected by a “feature bit mask”, and the bits of the feature mask can be set and deleted in different parts of the rendering pipeline. For instance, the Depth Pass may set the “Depth” feature bit, and a character rendering node may set the “Skinned” feature bit, resulting in the feature mask “Depth|Skinned”. A Shader can contain any number of variations, each with a specific feature mask. Thus a shader which supports rendering in the depth pass, and also supports skinning would implement (among others) a variation “Depth|Skinned” for rendering skinned geometry during the depth pass.&lt;/p&gt;  &lt;p&gt;The biggest problem with the current system is that ShaderVariables are so damn powerful, thanks to the FX system. FX implicitly caches the current value of shader variables, so that a variable can be set at any time before or after the shader is actually used for rendering. FX also tracks changes to shader variables and knows which shader variables need to be updated when it comes to rendering. This extra caching layer is actually not really required by Nebula3 and removing it allows for a much more streamlined implementation if FX is not available or not desirable.&lt;/p&gt;  &lt;p&gt;Here are the changes I currently have in mind:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;A lot of reflection information will not be available. A Shader object won’t be required to enumerate the shader parameters and query their type. The only information that will probably survive is whether a specific parameter exists, but not its datatype, array size, etc… This is not really a problem for a game application, since the reflection information is usually only needed in DCC tools.&lt;/li&gt;    &lt;li&gt;Querying the current value of a shader parameter won’t be possible (in fact that’s already not possible in N3, even though FX offers this feature).&lt;/li&gt;    &lt;li&gt;ShaderInstances will offer a way to setup shader parameters as “immutable”. Immutable parameters are set once but cannot be changed afterwards. For instance, the material parameters of a StateNode won’t be changed once they are initialized, and setting them up as immutable allows the shader to record them into some sort of opaque command buffer or state block and then completely forget about them (so it doesn’t have to keep track of immutable parameters at all once they have been setup).&lt;/li&gt;    &lt;li&gt;Mutable shader parameters (like the ModelViewProjection matrix) are not required to cache their current value, this means that N3 may only set mutable shader parameters after the ShaderInstance has been set as the active shader. This may be a bit inconvenient here and there, but it relieves the low-level shader system from a lot of house-keeping.&lt;/li&gt;    &lt;li&gt;With the 2 previous points a ShaderInstance doesn’t have to keep track of shader parameters at all. All the immutables are stored away in command buffers, and all the mutables could directly go through to the rendering API.&lt;/li&gt;    &lt;li&gt;It won’t be possible to change rasterization state through shader variables at all (like CullMode or AlphaRef - basically, everything that’s set inside a FX Technique), shader variables may only map to vertex- or pixel-shader uniform constants.&lt;/li&gt;    &lt;li&gt;N3 still needs to call a Commit() method on the shader instance after setting mutable parameters and before issuing the draw-call since depending on the platform, some housekeeping and batching may still be necessary for setting mutable parameters efficiently.&lt;/li&gt;    &lt;li&gt;Shared shader parameters will (probably) go away. They are convenient but hard to replicate on others platforms. Maybe a similar mechanism will be implemented through a new N3 class so that platform ports have more freedom in implementing shared shader parameters (shared parameters will likely have to be registered by N3 instead of being automatically setup by the platform’s rendering API).&lt;/li&gt;    &lt;li&gt;The last fix will be in the higher-level code where ModelNodeInstances are rendered:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Currently, draw-calls are grouped by their ShaderInstance, but those instance-groups themselves are not sorted in a particular order. In the future, rendering will also be sorted by Shader and active ShaderVariation, this allows to change the vertex and pixel shaders less frequently (changing the pixel shader is particularly bad).&lt;/li&gt;      &lt;li&gt;Currently, a ShaderInstance object contains a complete cloned FX effect instance, in the future, a shader instance will not use a cloned effect - instead, immutable parameters will be captured into a parameter block and mutable parameter changes will be routed directly to the “parent” FX effect.&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;p&gt;Another mid-term-goal I want to aim for is to reduce the number of per-draw-call shader-parameter-changes as much as possible. There are a lot of lighting parameters fed into the pixel shader for each draw call currently. Whether this means going to &lt;a href="http://diaryofagraphicsprogrammer.blogspot.com/2008/03/light-pre-pass-renderer.html" target="_blank"&gt;some sort of deferred rendering approach&lt;/a&gt; or maybe setting up per-model lighting parameters in a dynamic texture, or trying to move more work back into the vertex shader I don’t know yet.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7358572368078480318?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7358572368078480318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7358572368078480318' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7358572368078480318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7358572368078480318'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/06/more-streamlined-shader-system.html' title='A more streamlined shader system'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1307034525555320497</id><published>2009-06-20T15:38:00.001+01:00</published><updated>2009-06-20T15:38:52.421+01:00</updated><title type='text'>N3 I/O Tips &amp; Tricks</title><content type='html'>&lt;p&gt;Note: all of the following code-fragments assume:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;using namespace Util;        &lt;br /&gt;using namespace IO;         &lt;br /&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h4&gt;Working with Assigns&lt;/h4&gt;  &lt;p&gt;Assigns are path aliases which are used instead of hardwired file locations. This lets an N3 application use filenames which are independent from the host platform, actual Windows version, or Windows language version. The following “system assigns” are pre-defined in a standard Nebula3 application:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;home:&lt;/strong&gt; Points to the app’s installation directory, or (on console platforms) the root directory of the game content. The home: location should always be treated as read-only! &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;bin: &lt;/strong&gt;Points to the location where the app’s executable resides, should be treated as read-only (not available on console platforms) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;user: &lt;/strong&gt;On Windows, points to the logged-in user’s data directory (e.g. on Windows 7 this is c:\Users\[user]\Documents). Can be treated as read/write, and this is where profile-data and save-game-files should be saved. On consoles this assign may point to the save-location, or it may not be available at all (if saving game data is not handled through some sort of file system on that specific platform). &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;temp: &lt;/strong&gt;On Windows, this points to the logged-in user’s temp directory (e.g. on Windows 7 this is c:\Users\[user]\AppData\Local\Temp). This directory is read/write but applications should assume that files in this directory may disappear at any time. This assign is not available on console platforms. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;programs: &lt;/strong&gt;On Windows, this points to the standard location for programs (e.g. “c:\Program Files”) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;appdata: &lt;/strong&gt;On Windows, this points to the user’s AppData directory (e.g. c:\Users\[user]\AppData) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Additionally to these system assigns, Nebula3 sets up the following “content assigns” at startup which all applications can rely on:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;export:&lt;/strong&gt; points to the root of the directory where all game data files reside       &lt;ul&gt;       &lt;li&gt;&lt;strong&gt;ani: &lt;/strong&gt;root directory of animation files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;data:&lt;/strong&gt; root directory of general data files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;video:&lt;/strong&gt; root directory of movie files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;seq: &lt;/strong&gt;root directory of sequence files (e.g. engine-cutscenes) &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;stream:&lt;/strong&gt; root directory of streaming audio files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;tex: &lt;/strong&gt;root directory of texture files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;frame:&lt;/strong&gt; root directory of frame shader files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;mdl:&lt;/strong&gt; root directory of .n3 files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;shd: &lt;/strong&gt;root directory of shader files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;audio:&lt;/strong&gt; root directory for non-streaming audio files &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;sui:&lt;/strong&gt; root directory for “Simple GUI” scene files &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;More standard assigns may be added in the future.&lt;/p&gt;  &lt;p&gt;An application can define its own assigns or override existing assigns using the IO::AssignRegistry singleton:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;AssignRegistry::Instance()-&amp;gt;SetAssign(Assign(“bla”, “home:blub”));&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Ver"&gt;To use the new assign, simply put it at the beginning of a typical file path:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;“bla:readme.txt”&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This would resolve to the following absolute filename (assuming your app is called “MyApp” and located under the standard location for programs under Windows):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“C:\Program Files\MyApp\blub\readme.txt”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You can resolve a path name with assigns into an absolute file name through the AssignRegistry, this is usually necessary when working with 3rd party libs:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;String absPath = AssignRegistry::Instance()-&amp;gt;ResolveAssignsInString(“bla:readme.txt”);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Finally, Assigns are not restricted to file system locations:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;AssignRegistry::Instance()-&amp;gt;SetAssign(Assign(“bla”, “http://www.radonlabs.de/blub”));&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Listing directory content&lt;/h4&gt;  &lt;p&gt;You can list the files or subdirectories of a directory with pattern matching like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;// list all files in the app’s export directory        &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;Array&amp;lt;String&amp;gt; files = IoServer::Instance()-&amp;gt;ListFiles(“home:export”, “*”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// list all subdirectories in the app’s export directory        &lt;br /&gt;Array&amp;lt;String&amp;gt; dirs = IoServer::Instance()-&amp;gt;ListDirectories(“home:export”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// list all DDS textures of category “leafs”        &lt;br /&gt;Array&amp;lt;String&amp;gt; leafTextures = IoServer::Instance()-&amp;gt;ListFiles(“tex:leafs”, “*.dds”);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Note that the returned strings are not full pathnames, only the actul file- and directory-names!&lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Working with directories&lt;/h4&gt;  &lt;p&gt;You can create directories and subdirectories with a single method call:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;IoServer::Instance()-&amp;gt;CreateDirectory(“home:bla/blub/blob”);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This will also create all missing subdirectories as needed.&lt;/p&gt;  &lt;p&gt;You can delete the tail directory of a path, but the directory must be empty:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;IoServer::Instance()-&amp;gt;DeleteDirectory(“home:bla/blub/blob”);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This will delete the “blob” subdirectory only, and only if there are no files or subdirectories left under “blob”.&lt;/p&gt;  &lt;p&gt;You can check whether a directory exists:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;if (IoServer::Instance()-&amp;gt;DirectoryExists(“home:bla/blub”))        &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // directory exists         &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;NOTE:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;creating and deleting directories in archive files doesn’t work &lt;/li&gt;    &lt;li&gt;all directory functions only work in the file system, so a DirectoryExists(“http://www.radonlabs.de/bla”) will *not* work &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Working with files&lt;/h4&gt;  &lt;p&gt;The following IoServer methods are available for files, these all work directly with path names, so you don’t need to have an actual Stream object around:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;// check whether a file exists:        &lt;br /&gt;if (IoServer::Instance()-&amp;gt;FileExists(“home:readme.txt”)) …         &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// delete a file:        &lt;br /&gt;IoServer::Instance()-&amp;gt;DeleteFile(“home:readme.txt”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// copy a file:        &lt;br /&gt;IoServer::Instance()-&amp;gt;CopyFile(“home:src.txt”, “home:dst.txt”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// check if the read-only flag is set on a file:        &lt;br /&gt;if (IoServer::Instance()-&amp;gt;IsReadOnly(“home:src.txt”)) …&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// set the read-only flag on a file:        &lt;br /&gt;IoServer::Instance()-&amp;gt;SetReadOnly(“home:src.txt”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// getting the last modification time of a file:        &lt;br /&gt;FileTime fileTime = IoServer::Instance()-&amp;gt;GetFileWriteTime(“home:readme.txt”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// setting the last modification time of a file:        &lt;br /&gt;IoServer::Instance()-&amp;gt;SetFileWriteTime(“home:readme.txt”, fileTime);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;NOTE:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;DeleteFile(), SetReadOnly(), SetFileWriteTime() do not work in file archives &lt;/li&gt;    &lt;li&gt;CopyFile() doesn not work if the destination is located in a file archive &lt;/li&gt;    &lt;li&gt;all of these functions only work with file system paths (not “http://…”) &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;How to get the size of a file&lt;/h4&gt;  &lt;p&gt;Currently, the only way to query the size of a file is through an open IO::Stream object. This may change in the future though.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“home:readme.txt”);        &lt;br /&gt;if (stream-&amp;gt;Open())         &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Stream::Size fileSize = stream-&amp;gt;GetSize();         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; stream-&amp;gt;Close();         &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Working with file archives&lt;/h4&gt;  &lt;p&gt;You can mount zip archives as an overlay over the actual file system:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;IoServer::Instance()-&amp;gt;MountArchive(“home:archive.zip”);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;All file system accesses will first check mounted archives (in mount order) before falling back to the actual file system.&lt;/p&gt;  &lt;p&gt;Archives have the following restrictions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;writing to archives is not supported&lt;/li&gt;    &lt;li&gt;the archive filesystem will keep some sort of table-of-content in memory as long as an archive is mounted, the actually required size of the TOC differs by platform.&lt;/li&gt;    &lt;li&gt;in the current zlib-based implementation, complete files are decompressed into memory, thus opening a 100 MB file from an archive will also allocate 100 MB of memory until the file is closed &lt;/li&gt;    &lt;li&gt;for the above reason, streaming from archive files doesn’t make sense, thus things like streaming audio wave banks or movie files should not be placed into archive files &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;On console platforms platform-native file archive formats are used if available (e.g. .PSARC on PS3 or .ARC on Wii) which usually have less restrictions and are better optimized for the platform then plain ZIP support. The Xbox360 port currently uses the standard zlib implementation but this will very likely change in the future.&lt;/p&gt;  &lt;p&gt;On Windows (and currently Xbox360), zip support is handled through zlib.&lt;/p&gt;  &lt;p&gt;You can add support for other archive formats by deriving subclasses from the classes under foundation/io/archfs, but currently it is not possible to mix different archive formats in one application (because you need to decide on a specific archive-filesystem-implementation at compile-time).&lt;/p&gt;  &lt;p&gt;You can turn off the archive file-system layer completely through IoServer::SetArchiveFileSystemEnabled(false). All file accesses will then go directly into the actual file system. This is useful for tools which need to make sure that they don’t accidently read data from an archive file.&lt;/p&gt;  &lt;p&gt;Nebula3 defines a “standard archive” where all game data is located. The data in the archive is located under the “export:” assign on all platforms. The actual archive filenames for the various platforms are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Win32: &lt;strong&gt;home:export_win32.zip&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Xbox360: &lt;strong&gt;home:export_xbox360.zip&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Wii: &lt;strong&gt;home:export_wii.arc&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;PS3: &lt;strong&gt;home:export_ps3.psarc&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The &lt;strong&gt;archiver3.exe&lt;/strong&gt; tool takes care about generating those standard archives as part of the build process, when generating data for console platforms, the actual console SDK must be installed &lt;/p&gt;  &lt;p&gt;(however, please note that we cannot currently license the N3 console ports to other companies anyway).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Working with the SchemeRegistry&lt;/h4&gt;  &lt;p&gt;The IO::SchemeRegistry singleton associates URI schemes (those things at the start of an URI, e.g. “file://…”, “http://…”) with Stream classes. You can override the pre-defined scheme associations or register your own scheme with a stream class of your own:&lt;/p&gt;  &lt;blockquote&gt;&lt;font face="Courier New"&gt;     &lt;p&gt;       &lt;br /&gt;// register my own scheme and stream class:         &lt;br /&gt;SchemeRegistry::Instance()-&amp;gt;RegisterUriScheme(“myscheme”, MyStream::RTTI);&lt;/p&gt;      &lt;p&gt;// create a stream object by URI:        &lt;br /&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“myscheme://bla/blub”);&lt;/p&gt;      &lt;p&gt;// the returned stream object should be an instance of our derived class:        &lt;br /&gt;n_assert(stream-&amp;gt;IsInstanceOf(MyStream::RTTI));&lt;/p&gt;   &lt;/font&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;You can also override standard associations to route all file accesses through your own stream class like this:&lt;/font&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;// override the file scheme to use our own stream class:        &lt;br /&gt;SchemeRegistry::Instance()-&amp;gt;RegisterUriScheme(“file”, MyStream::RTTI);&lt;/p&gt;   &lt;/blockquote&gt;    &lt;h4&gt;&lt;/h4&gt; &lt;/blockquote&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;&lt;strong&gt;&lt;font color="#aa0033" size="3"&gt;Reading and writing XML files&lt;/font&gt;&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;Attach an IO::XmlReader object to an IO::Stream object to parse the content of an XML file. The XmlReader can access nodes through path names, so you can navigate XML nodes like files in a file system. The XmlReader tracks a “current node” internally, like the “current directory” in a file system API.&lt;/p&gt;  &lt;blockquote&gt;&lt;font face="Courier New"&gt;     &lt;p&gt;// create an XML reader and parse the file “home:test.xml”:        &lt;br /&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“home:test.xml”);         &lt;br /&gt;Ptr&amp;lt;XmlReader&amp;gt; xmlReader = XmlReader::Create();         &lt;br /&gt;xmlReader-&amp;gt;SetStream(stream);         &lt;br /&gt;if (xmlReader-&amp;gt;Open())         &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // test if a specific node exists in the XML file:         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (xmlReader-&amp;gt;HasNode(“/Nebula3/Models”))…&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // position the current node on “/Nebula3/Models”:        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; xmlReader-&amp;gt;SetToNode(“/Nebula3/Models”);&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // iterate over child nodes of current node:        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (xmlReader-&amp;gt;SetToFirstChild()) do         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; …         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } while (xmlReader-&amp;gt;SetToNextChild());&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // iterate over child nodes named “Model”:        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (xmlReader-&amp;gt;SetToFirstChild(“Model”)) do         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; …         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } while (xmlReader-&amp;gt;SetToNextChild(“Model”));&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // test if the current node has a “name” attribute        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // and read its value as a string:         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (xmlReader-&amp;gt;HasAttr(“name”))         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; String name = xmlReader-&amp;gt;GetString(“name”);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // if the “name” is optional, you can also do this in one line of         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // code and provide a default value, if “name” is not present:         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; String name = xmlReader-&amp;gt;GetOptString(“name”, “DefaultName”);&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // you can also read simple data types directly:        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; int intVal = xmlReader-&amp;gt;GetInt(“intAttr”);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; float floatVal = xmlReader-&amp;gt;GetFloat(“floatAttr”);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; …&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // to read the current node’s content (&amp;lt;Node&amp;gt;Content&amp;lt;/Node&amp;gt;):        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (xmlReader-&amp;gt;HasContent())         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; String content = xmlReader-&amp;gt;GetContent();         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;      &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/font&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;To create a new XML file, use an XmlWriter in a similar fashion:&lt;/font&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“temp:bla.xml”);          &lt;br /&gt;Ptr&amp;lt;XmlWriter&amp;gt; xmlWriter = XmlWriter::Create();           &lt;br /&gt;xmlWriter-&amp;gt;SetStream(stream);           &lt;br /&gt;if (xmlWriter-&amp;gt;Open())           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // write a node hierarchy, and add a few attributes to the leaf node:           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;BeginNode(“Nebula3”);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;BeginNode(“Models”);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;BeginNode(“Model”);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;SetString(“name”, “A Model”);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;SetInt(“intVal”, 20);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; …           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;EndNode();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;EndNode();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;EndNode();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // close xml writer, this will also close the stream object           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; xmlWriter-&amp;gt;Close();           &lt;br /&gt;}           &lt;br /&gt;          &lt;br /&gt;// you can also write a comment to the XML file:           &lt;br /&gt;xmlWriter-&amp;gt;WriteComment(“A Comment”);           &lt;br /&gt;          &lt;br /&gt;// or write the content enclosed by the current node:           &lt;br /&gt;xmlWriter-&amp;gt;WriteContent(“Content”);&lt;/font&gt;         &lt;br /&gt;        &lt;br /&gt;&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;Additional notes on XML processing:&lt;/font&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;font face="Verdana"&gt;XmlReader and XmlWriter use TinyXml internally which has a tiny modification to read and write data through Nebula3 stream objects instead of the host filesystem&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Verdana"&gt;Reading large XML files can be very slow because of the thousands of small allocations going on for string data, thus reading XML files is not recommended for actual game applications, use optimized binary formats, or Nebula3’s database subsystem instead.&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Verdana"&gt;There’s currently no easy way to read an XML file, modify it and write it back.&lt;/font&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;h4&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/h4&gt;    &lt;h4&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/h4&gt;    &lt;h4&gt;&lt;font face="Verdana"&gt;Working with BinaryReader / BinaryWriter&lt;/font&gt;&lt;/h4&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;The IO::BinaryReader and IO::BinaryWriter classes implement access to streams as a sequence of simple typed data elements like int, float, float4 or strings with automatic byte order conversion for different platforms:&lt;/font&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;&lt;font face="Courier New"&gt;// read data from a file using BinaryReader:          &lt;br /&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“home:bla.bin”);           &lt;br /&gt;Ptr&amp;lt;BinaryReader&amp;gt; reader = BinaryReader::Create();           &lt;br /&gt;reader-&amp;gt;SetStream(stream);           &lt;br /&gt;if (reader-&amp;gt;Open())           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; uchar ucharVal = binaryReader-&amp;gt;ReadUChar();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; float floatVal = binaryReader-&amp;gt;ReadFloat();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; String strVal&amp;#160; = binaryReader-&amp;gt;ReadString();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Math::matrix44 matrixVal = binaryReader-&amp;gt;ReadMatrix44();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Blob blob = binaryReader-&amp;gt;ReadBlob();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; …           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; reader-&amp;gt;Close();           &lt;br /&gt;}           &lt;br /&gt;          &lt;br /&gt;// writing data is just the other way around:           &lt;br /&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“temp:bla.bin”);           &lt;br /&gt;Ptr&amp;lt;BinaryWriter&amp;gt; writer = BinaryWriter::Create();           &lt;br /&gt;writer-&amp;gt;SetStream(stream);           &lt;br /&gt;if (writer-&amp;gt;Open())           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; writer-&amp;gt;WriteUShort(123);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; writer-&amp;gt;WriteString(“Bla”);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; …           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; writer-&amp;gt;Close();           &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;The byte order of BinaryReader/Writer is by default set to ByteOrder::Host (the host platform’s native byte order). You can enable automatic byte order conversion with the SetStreamByteOrder() method on BinaryReader and BinaryWriter. For instance, to create a binary file for one of the PowerPC-driven consoles from a tool running on the PC you would setup the BinaryWriter like this:&lt;/font&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“temp:bla.bin”);          &lt;br /&gt;Ptr&amp;lt;BinaryWriter&amp;gt; writer = BinaryWriter::Create();           &lt;br /&gt;writer-&amp;gt;SetStream(stream);           &lt;br /&gt;writer-&amp;gt;SetStreamByteOrder(System::ByteOrder::BigEndian);           &lt;br /&gt;if (writer-&amp;gt;Open()) …&lt;/font&gt;         &lt;br /&gt;&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;Automatic byte order conversion naturally doesn’t work for Util::Blob objects, since the reader/writer doesn’t know how the data inside the blob is structured.&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;Additional Notes:&lt;/font&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;font face="Verdana"&gt;Only use BinaryReader / BinaryWriter in an actual game project when absolutely necessary. For the sake of efficient and fast loading from disk it’s usually better to prepare any sort of game data as a native memory dump which can be loaded with a simple Stream::Read() and immediately used without any parsing or data conversions going on during load. Time spent in the build pipeline is a thousand times cheaper then time spent waiting for a level to load, thus BinaryReader and BinaryWriter are much better used in offline tools!&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Verdana"&gt;Even in offline tools, BinaryReader/Writer can be very slow when processing thousands of data elements, since reading or writing each little data element will cause a complete round-trip through the ReadFile / WriteFile functions of the host’s operating system. Use the &lt;strong&gt;SetMemoryMappingEnabled(true)&lt;/strong&gt; method to speed up reading and writing of data elements drastically by caching the data in memory. In the BinaryReader, this will load the entire file into memory in Open(), and in the BinaryWriter, all writes will go into a memory buffer first, which will then be dumped to a file in Close() with a single Write().&lt;/font&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;h4&gt;&lt;font face="Verdana"&gt;Reading Excel XML files with Nebula3&lt;/font&gt;&lt;/h4&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;You can use the IO::ExcelXmlReader stream reader class to parse files saved in XML format from MS Excel (all versions should work, but when in doubt, save as Excel 2003 XML file). After opening an Excel file, the content of the file can be accessed by table, column and row index:&lt;/font&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;Stream&amp;gt; stream = IoServer::Instance()-&amp;gt;CreateStream(“home:excelsheet.xml”);          &lt;br /&gt;Ptr&amp;lt;ExcelXmlReader&amp;gt; reader = ExcelXmlReader::Create();           &lt;br /&gt;reader-&amp;gt;SetStream(stream);           &lt;br /&gt;if (reader-&amp;gt;Open())           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // NOTE: when working with the left-most “default” table,           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // we can simply omit the table index in all methods.           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; //&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Test if a column exists in the left-most table:           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (xmlReader-&amp;gt;HasColumn(“Bla”))           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // get the column index (returns InvalidIndex if not exists)           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IndexT colIndex = xmlReader-&amp;gt;FindColumnIndex(“Bla”);           &lt;br /&gt;          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // iterate over all rows and read content of column “Bla”:           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IndexT rowIndex;           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SizeT numRows = xmlReader-&amp;gt;GetNumRows();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (rowIndex = 0; rowIndex &amp;lt; numRows; rowIndex++)           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // get the content of cell at (rowIndex,colIndex):           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; String elm = xmlReader-&amp;gt;GetElement(rowIndex, colIndex);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }           &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;&lt;font face="Verdana"&gt;You can also access specific tables in an Excel file. In this case, an additional tableIndex parameter is used in most methods:&lt;/font&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;&lt;font face="Courier New"&gt;// get the number of tables in the Excel file:          &lt;br /&gt;SizeT numTables = xmlReader-&amp;gt;GetNumTables();&lt;/font&gt;&lt;/p&gt;      &lt;p&gt;&lt;font face="Courier New"&gt;// find a table index by name (return InvalidIndex if not exists)          &lt;br /&gt;IndexT tableIndex = xmlReader-&amp;gt;GetTableIndex(“TableName”);&lt;/font&gt;&lt;/p&gt;     &lt;font face="Courier New"&gt;// get the name of table at index        &lt;br /&gt;const String&amp;amp; tableName = xmlReader-&amp;gt;GetTableName(tableIndex); &lt;/font&gt;      &lt;p&gt;&lt;font face="Courier New"&gt;// to access a particular table, simply add the table index as last          &lt;br /&gt;// parameter to all other methods:           &lt;br /&gt;SizeT numRowsOfTable = xmlReader-&amp;gt;GetNumRows(tableIndex);           &lt;br /&gt;SizeT numColsOfTable = xmlReader-&amp;gt;GetNumColumns(tableIndex);           &lt;br /&gt;bool hasColumn = xmlReader-&amp;gt;HasColumn(“Bla”, tableIndex);           &lt;br /&gt;String elm = xmlReader-&amp;gt;GetElement(rowIndex, colIndex, tableIndex);           &lt;br /&gt;…&lt;/font&gt;&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;Note that Excel XML files come with a lot more fluff then actual data, so reading an Excel table bigger then a few dozen or hundred kBytes is EXTREMELY slow. Do not use Excel XML files directly in your game application, but only as source data files in the content pipeline, and convert them to binary files or write them into an SQLite database during the build process for more efficient consumption by the game application.&lt;/p&gt;    &lt;h4&gt;&amp;#160;&lt;/h4&gt;    &lt;h4&gt;How to register you own ConsoleHandler&lt;/h4&gt;    &lt;p&gt;Console handlers are attached to the IO::Console singleton to handle console output and optionally provide text input from a console. When Nebula3 starts up, a standard console handler is created in IO::Console::Open() which (under Windows) will route output to STD_OUTPUT_HANDLE and STD_ERROR_HANDLE, and provide non-blocking input from STD_INPUT_HANDLE. When not compiled with the PUBLIC_BUILD define, all text output will also go to OutputDebugString() and thus show up in the debugger, which is especially useful when running a windowed application (as opposed to a console application) under Windows.&lt;/p&gt;    &lt;p&gt;On console platforms, the default ConsoleHandlers route all text output to the debug out channel.&lt;/p&gt;    &lt;p&gt;Nebula3 provides 2 optional console handlers:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;IO::LogFileConsoleHandler: &lt;/strong&gt;can be used to capture all text output into a log file &lt;/li&gt;      &lt;li&gt;&lt;strong&gt;IO::HistoryConsoleHander:&lt;/strong&gt; captures console output into an in-memory ring buffer, this is currently used by the IO::ConsolePageHandler for the Debug-HTTP-Server in order to provide a snapshot of console output in a web browser connected to the N3 application. &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Registering your own console handler is easy: just derive a subclass from IO::ConsoleHandler, override a few virtual methods, and call IO::Console::AttachHandler() with a pointer to an instance of your derived class early in your application.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Phew, I think that’s all the stuff that’s good-to-know when doing file IO in Nebula3. Please note that this was all about synchronous I/O. For asynchronous IO the IO::IoInterface interface-singleton is used, this simply launches a thread with its own thread-local IoServer, and IO operations are sent to the IO thread using Message objects (which in turn need to be checked for completion of the IO operation). It’s not much more complicated then synchronous IO. However I’m planning to do a few changes under the hood for asynchronous IO to enable better platform-specific optimizations in the future.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1307034525555320497?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1307034525555320497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1307034525555320497' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1307034525555320497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1307034525555320497'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/06/n3-io-tips-tricks.html' title='N3 I/O Tips &amp;amp; Tricks'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6674488246124032560</id><published>2009-06-16T08:59:00.001+01:00</published><updated>2009-06-16T08:59:40.620+01:00</updated><title type='text'>Nebula3 RTTI Tips &amp; Tricks</title><content type='html'>&lt;p&gt;Note: I have omitted the namespace prefixes and ‘using namespace xxx’ statements in the code below to improve readability. Also, since I didn’t run the code through a compiler, there may be a lot of typos.&lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Don’t be confused by Rtti vs. RTTI:&lt;/h4&gt;  &lt;p&gt;Rtti is the class name, MyClass::RTTI is the name of the Rtti-object of a class. Every RefCounted derived class has exactly one static instance of Core::Rtti, which is initialized before main() is entered.&lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Check whether an object is an instance of a specific, or of a derived class:&lt;/h4&gt;  &lt;p&gt;This is the standard feature of the Nebula3 RTTI system, checking whether an object can safely be cast to a specific class interface: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;// check whether obj is instance of a specific class:        &lt;br /&gt;if (obj-&amp;gt;IsInstanceOf(MyClass::RTTI)) …&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// check whether obj is instance of class, or a derived class:        &lt;br /&gt;if (obj-&amp;gt;IsA(MyClass::RTTI))…&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Compared to Nebula2, N3’s RTTI check is extremely fast (in N2, it was necessary to convert a class name string into a pointer first before doing the check). In N3, RTTI checks are simple pointer comparisons. The IsA() method is a bit slower if the class doesn’t match since it needs to walk the inheritance hierarchy towards the root. Because of this it is always better to use the IsInstanceOf() method if possible, since this is always only a single pointer comparison.&lt;/p&gt;  &lt;p&gt;Both methods also exist as class-name and class-fourcc versions, but of course these are both slower then the methods which directly work with the RTTI objects:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;if (obj-&amp;gt;IsInstanceOf(“MyNamespace::MyClass”)) …        &lt;br /&gt;if (obj-&amp;gt;IsInstanceOf(FourCC(‘MYCL’))…&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;if (obj-&amp;gt;IsA(“MyNamespace::MyClass”))…        &lt;br /&gt;if (obj-&amp;gt;IsA(FourCC(‘MYCL’))…&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Using Ptr&amp;lt;&amp;gt; cast methods for safe-casting:&lt;/h4&gt;  &lt;p&gt;The Ptr&amp;lt;&amp;gt; class comes with 3 cast methods, 2 for safe up- and down-casts, and one unsafe-but-fast C-style cast. To do a down-cast (from a general parent class down to a specialized sub-class) you can do this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;// assume that res is a Ptr&amp;lt;Resource&amp;gt;, and safely down-cast        &lt;br /&gt;// it to a Ptr&amp;lt;D3D9Texture&amp;gt; (D3D9Texture is a subclass of Resource):         &lt;br /&gt;const Ptr&amp;lt;D3D9Texture&amp;gt;&amp;amp; d3d9Tex = res.downcast&amp;lt;D3D9Texture&amp;gt;();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This will generate a runtime-error if tex is not a D3D9Texture object.&lt;/p&gt;  &lt;p&gt;Safely casting upwards in the inheritance hierarchy works as well:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;const Ptr&amp;lt;Resource&amp;gt;&amp;amp; res = d3d9Tex.upcast&amp;lt;Resource&amp;gt;();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;An unsafe C-style cast is done like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;const Ptr&amp;lt;Resource&amp;gt;&amp;amp; res = d3d9Tex.cast&amp;lt;Resource&amp;gt;();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;An unsafe cast is the fastest (in release mode, the compiler should optimize the method call into nothing), but of course it also makes it extremely easy to shoot yourself in the foot. The 2 safe-cast methods call the Rtti::IsDerivedFrom() method, no temporary Ptr&amp;lt;&amp;gt; object will be created since they return a const-ref.&lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Query RTTI objects directly:&lt;/h4&gt;  &lt;p&gt;You can directly query many class properties without having an actual object of the class around:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;// get the name of a class:        &lt;br /&gt;const String&amp;amp; className = MyClass::RTTI.GetName();&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// get the FourCC identifier of aclass:        &lt;br /&gt;FourCC classFourCC = MyClass::RTTI.GetFourCC();&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// get a pointer to the Rtti object of the parent class        &lt;br /&gt;// (returns 0 when called on RefCounted::RTTI)&lt;/font&gt;&lt;font face="Courier New"&gt;        &lt;br /&gt;Rtti* parentRtti = MyClass::RTTI.GetParent();&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;// check if a class is derived from this class:        &lt;br /&gt;// by Rtti object:&lt;/font&gt;&lt;font face="Courier New"&gt;        &lt;br /&gt;if (MyClass::RTTI.IsDerivedFrom(OtherClass::RTTI)) …         &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;// by class name:        &lt;br /&gt;if (MyClass::RTTI.IsDerivedFrom(“MyNamespace::OtherClass”)) …         &lt;br /&gt;// by class fourcc:         &lt;br /&gt;if (MyClass::RTTI.IsDerivedFrom(FourCC(‘OTHR’))…&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You can check two Rtti objects for equality or inequality:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;const Rtti&amp;amp; otherRtti = …;        &lt;br /&gt;if (MyClass::RTTI == otherRtti)…         &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;if (MyClass::RTTI != otherRtti)…&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Since it is guaranteed that only one Rtti object exists per class this is equivalent with comparing the addresses of 2 Rtti objects (and that’s in fact what the equality and inequality operators do internally). &lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Create objects directly through the RTTI object:&lt;/h4&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;MyClass&amp;gt; myObj = (MyClass*) MyClass::RTTI.Create();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The old-school C-style cast looks a bit out of place but is currently necessary because the Rtti::Create() method returns a raw pointer, not a smart-pointer.&lt;/p&gt;  &lt;p&gt;Creating an object through the RTTI object instead of the static MyClass::Create() method is useful if you want to hand the type of an object as an argument to a method call like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;RefCounted&amp;gt; CreateObjectOfAnyClass(const Rtti&amp;amp; rtti)        &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return rtti.Create();         &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is a lot faster then the 2 other alternatives, creating the object through its class name or class fourcc identifier.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Create objects by class name or FourCC identifier&lt;/h4&gt;  &lt;p&gt;You can use the Core::Factory singleton to create RefCounted-derived objects by class name or by a FourCC identifier:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;MyClass&amp;gt; obj = (MyClass*) Factory::Instance()-&amp;gt;Create(“MyNamespace::MyClass”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;Ptr&amp;lt;MyClass&amp;gt; obj = (MyClass*) Factory::Instance()-&amp;gt;Create(FourCC(‘MYCL’));&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is mainly useful for serialization code, or if the type of an object must be communicated over a network connection.&lt;/p&gt;  &lt;h5&gt;&lt;font face="Courier New"&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;font face="Courier New"&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;font face="Courier New"&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/h5&gt;  &lt;h4&gt;&lt;font face="Courier New"&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/h4&gt;  &lt;h4&gt;&lt;font face="Courier New"&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/h4&gt;  &lt;h4&gt;&lt;font face="Courier New"&gt;&lt;font face="Verdana"&gt;Lookup the RTTI object of a class through the Core::Factory singleton&lt;/font&gt;&lt;/font&gt;&lt;/h4&gt;  &lt;p&gt;You can get a pointer to the static RTTI object of a class by class name or class FourCC identifier:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;const Rtti* rtti = Factory::Instance()-&amp;gt;GetClassRtti(“MyNamespace::MyClass”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;const Rtti* rtti = Factory::Instance()-&amp;gt;GetClassRtti(FourCC(‘MYCL’));&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This will fail hard if the class doesn’t exist, you can check whether a class has been registered with the factory using the ClassExists() methods:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;bool classExists = Factory::Instance()-&amp;gt;ClassExists(“MyNamespace::MyClass”);&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;bool classExists = Factory::Instance()-&amp;gt;ClassExists(FourCC(‘MYCL’));&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;h5&gt;&amp;#160;&lt;/h5&gt;  &lt;h4&gt;Troubleshooting&lt;/h4&gt;  &lt;p&gt;There are 2 common problems with Nebula3’s RTTI system.&lt;/p&gt;  &lt;p&gt;When writing a new class, it may happen that the FourCC code of the class is already taken. In this case, an error dialog will popup at application start which looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_cWdorEDEaNg/SjdQ6jDlYkI/AAAAAAAAAH8/-3PfGpoQJZk/s1600-h/rtti_collision4.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="rtti_collision" border="0" alt="rtti_collision" src="http://lh5.ggpht.com/_cWdorEDEaNg/SjdQ6-U2w5I/AAAAAAAAAIA/b5Mr9Zrtq1I/rtti_collision_thumb2.jpg?imgmax=800" width="528" height="190" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;To fix this collision, change the FourCC code of one of the affected classes and recompile.&lt;/p&gt;  &lt;p&gt;The other problem is that a class doesn’t register at application startup because the constructor of its static RTTI object has been “optimized away” by the linker. This happens when there’s no actual C++ code in the application which directly uses this class. This is the case if an object is created through N3’s create-by-class-name or create-by-class-fourcc mechanism and the class is only accessed indirectly through virtual method calls.&lt;/p&gt;  &lt;p&gt;In this case the linker will drop the .obj module of this class completely since there are no calls from the outside into the object module. That’s a neat optimization to keep the executable size small, and it works great with the static object model of plain C++, but with Nebula3’s dynamic object model we need to trick the linker into linking “unused” classes into the executable. We don’t have to do this for every RefCounted-derived class fortunately, only for specific parts of the inheritance hierarchy (for instance subclasses of ModelNode and ModelNodeInstance in the Render layer, or subclasses of Property in the Application layer)&lt;/p&gt;  &lt;p&gt;To prevent the linker from dropping a class the following procedure is recommended: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;add a __RegisterClass(MyClass) macro to a central .h ‘class registry’ header file &lt;/li&gt;    &lt;li&gt;include this header file into a .cc file which definitely won’t be dropped by the linker &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The header file &lt;strong&gt;/nebula3/code/render/render_classregistry.h&lt;/strong&gt; is an example for such a centralized class registry header.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6674488246124032560?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6674488246124032560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6674488246124032560' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6674488246124032560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6674488246124032560'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/06/nebula3-rtti-tips-tricks.html' title='Nebula3 RTTI Tips &amp;amp; Tricks'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_cWdorEDEaNg/SjdQ6-U2w5I/AAAAAAAAAIA/b5Mr9Zrtq1I/s72-c/rtti_collision_thumb2.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-775574926274955190</id><published>2009-06-06T14:39:00.001+01:00</published><updated>2009-06-06T14:39:56.192+01:00</updated><title type='text'>Tidbits</title><content type='html'>&lt;p&gt;I must admit that I’m completely hyped for the Xbox team’s new “interaction system” Project Natal, especially since &lt;a href="http://www.youtube.com/watch?v=Jd3-eiid-Uw" target="_blank"&gt;this guy&lt;/a&gt; has been part of the team (Microsoft sure knows how to grab the relevant people). One has to look through the silly demos though (using a car racing game to demonstrate “controller free gaming” is kind of stupid when in the real world you’re sitting *inside* a huge freaking controller, which has a much more complex interface then any input device used for gaming and requires extremely skillful use of both hands and feet…). &lt;/p&gt;  &lt;p&gt;It’s fascinating to think about how much more information a game suddenly has about the world on the other side of the wall. With mouse/keyboard, a game pad, or even a Wiimote, the button presses, pointer positions, analog sliders and acceleration vectors only provide a handful of values, a few hundred bits of information maybe. That’s like a few tiny lights in a vast dark ocean. But if the currently available infos are somewhat correct, Natal provides per-pixel color and depth-information as well as a microphone array for spotting sound sources, everything pre-processed in meaningful ways by the software (that’s the important part which differentiates it from something simple like a web cam). That’s like a sunrise in the dark ocean! The game is suddenly able to see and hear what’s happening in that strange parallel universe called “real world”, and the software (which is hopefully provided with the 360 SDK) is the brain which interprets that information. That’s another great thing, all the interesting stuff happens in the software and can be improved with a simple software update, instead of trying to sell another hardware addon like the Motion Plus to baffled players.&lt;/p&gt;  &lt;p&gt;Now the only question is how to prevent walking into the Wii trap and not flood the 360 with stupid mini-games (IMHO mini-games are to game designers what the crates are for level designers: their last resort if they run out of ideas). It would be a terrible shame if this great technology is only used for Wii Play clones and silly “family games”. If Natal is rejected by the 360’s native hardcore crowd (yes I said the dirty word, there is no such thing as a “casual Xbox player”), it will soon fade into oblivion just as the current Vision Camera. I really doubt that Natal will cause casuals to forget about their Wii and convert to the 360 en mass. That ship has sailed long ago, maybe it could happen with the next console generation, or if Microsoft does a really big re-launch of a theoretical “Natal 360” which needs to look a lot slicker and sexier then the current 360. Any way, for the games audience, I think Microsoft should first try to sell Natal to the hardcore, and that’s not done with some silly ball catching or tennis demos, but with full-frontal science fiction shit like this: &lt;a href="http://www.youtube.com/watch?v=UUuRqzVhJmA" target="_blank"&gt;http://www.youtube.com/watch?v=UUuRqzVhJmA&lt;/a&gt; (although this is a conventional multi-touch device, not Natal, but you get the idea). For marketing to the casuals, concentrate on the 360 as a media device (now that was the right step in one of the demo videos, demonstrate how to watch a movie without having to the mess around with remote controls – because the one thing that’s much more complicated then a game pad is a remote control with dozens of tiny buttons).&lt;/p&gt;  &lt;p&gt;I think the best way to design a Natal game is to pretend that gamepads, keyboard and pointing devices never existed, go back to the 60’s or even the 50’s and create some sort of alternate future without keyboards, mice and gamepads. This is hard and will take a lot of time, since our current gaming genres are the result of decades of joint evolution of game play and input methods. Simply putting a new input scheme over existing games won’t work very well (I think the Wii has shown this already). But on the other hand, the first thing that you’re telling a PC game designer or programmer is to forget that mouse/keyboard ever existed when he’s starting to work on a console game and fully embrace the platform’s controller as if it would be the only input device in the whole universe. Switching to this new state of mind can be incredibly hard and some will never be able to do it, but with an open mind this often works surprisingly well.&lt;/p&gt;  &lt;p&gt;Some unrelated stuff:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Man, I hope 70 Euros isn’t becoming the new standard price for Xbox360 games in Germany (that’s about 100 US-$!). 60 Euros was already a shocker when the 360 launched. 70 Euros is waaayyy beyond impulse-buy-territory for me, especially when there’s only a few hours of entertainment in a game which is becoming more and more common. I’m currently extremely selective when buying new games, I think I only bought one or two new games this year, instead of almost one game per month in the past. I can’t imagine that this pricing strategy is good for the 360-platform in Germany, since people will only buy the very few big blockbusters and skip everything else, or get the cheaper (and most often better) UK versions. &lt;/li&gt;    &lt;li&gt;Very cool news: Bethesda will offer the Fallout 3 DLC on discs! I have skipped all but the first addons for Fallout 3 because they’re only available in the German language version. With the disc release I can finally order the proper English version and don’t have to live with the poor German localization.&lt;/li&gt;    &lt;li&gt;My &lt;a href="http://flohofwoe.blogspot.com/2008/12/games-of-year.html"&gt;wish from last year has been granted&lt;/a&gt;! Full game downloads on Xbox Live starting August 2009! Maybe I should consider a career as a fortune-teller or analyst hehe…&lt;/li&gt;    &lt;li&gt;We got a couple of those slick new PS3 devkits (the new ones in standard PS3 cases, not those older 19” rack monsters) and have started the Nebula3 PS3 port already. We’re putting a proper team of 4 behind this so the circle will soon be complete :) I’m quite happy with the progress so far. The SDK is very complete, the tools are nice enough (pretty good VStudio integration, thank God). Not quite as cool as the 360 stuff, but that’s more a question of personal taste and probably not objective. The PS3 SDK seems to have made great strides since the PS3 launch, and I think many of the negativity on the internet surrounding the PS3 development stems from those early days (which we haven’t experienced ourselves).&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That’s it for now, I’m going to nose around the PS3 SDK docs a bit now, perfect activity for a Saturday afternoon :)&lt;/p&gt;  &lt;p&gt;-Floh.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-775574926274955190?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/775574926274955190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=775574926274955190' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/775574926274955190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/775574926274955190'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/06/tidbits.html' title='Tidbits'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-967474568828017914</id><published>2009-05-27T18:43:00.001+01:00</published><updated>2009-05-27T18:56:06.859+01:00</updated><title type='text'>New Laboratory</title><content type='html'>&lt;p&gt;A few pics from our new office right at the &lt;a href="http://maps.google.com/maps/mm?ie=UTF8&amp;amp;hl=en&amp;amp;t=h&amp;amp;ll=52.522116,13.41215&amp;amp;spn=0.005046,0.009656&amp;amp;z=17" target="_blank"&gt;Alexanderplatz&lt;/a&gt; in the center of Berlin. The office is still sort-of under construction because of some delays, but it will be finished soon (in about 2 weeks hopefully). The good thing is that it is within walking distance from my home (about 3 kilometers), and its a very nice walk (at least if the weather plays well).&lt;/p&gt;  &lt;p&gt;The new office is actually a LOT bigger then what's visible on the photos. We decided on a floor plan where we can have around 5..16 people in one room which is big enough to enable direct communication between team members, but not big enough to become noisy. There are several meeting rooms, a chill out area, 3 kitchens, a server room plus a fallback server room, and enough room for future growth (we had to move to a bigger office every 2 years since Radon Labs GmbH exists, hopefully the new office is big enough so that we can stay a bit longer this time around, because as far as Berlin is concerned, this is pretty much the perfect location). &lt;/p&gt;  &lt;p&gt;Here's what we see when looking out of the office towards the Fernsehturm:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/Sh17xCjCiUI/AAAAAAAAAHc/hPGb4TwR8nc/s1600-h/IMG_6187%5B9%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="510" alt="IMG_6187" src="http://lh3.ggpht.com/_cWdorEDEaNg/Sh17x1qqqWI/AAAAAAAAAHg/EAdRSePSejI/IMG_6187_thumb%5B7%5D.jpg?imgmax=800" width="340" border="0" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;That's what it looks like in the areas that are still under construction, this is going to become one of the meeting rooms:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_cWdorEDEaNg/Sh17yANN3kI/AAAAAAAAAHk/7j6Eon7qMHM/s1600-h/IMG_6234%5B7%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="393" alt="IMG_6234" src="http://lh4.ggpht.com/_cWdorEDEaNg/Sh17y-NPEkI/AAAAAAAAAHo/saThasBzbew/IMG_6234_thumb%5B5%5D.jpg?imgmax=800" width="586" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And that's what the team offices look like (this is the room of the Drakensang character department, who are presumably out to lunch or fleeing from the alien attack or something):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/Sh17za4BBrI/AAAAAAAAAHs/7oChE-wBL_U/s1600-h/IMG_6203%5B10%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="391" alt="IMG_6203" src="http://lh4.ggpht.com/_cWdorEDEaNg/Sh17z5b7-vI/AAAAAAAAAHw/uW5JYcZX_io/IMG_6203_thumb%5B8%5D.jpg?imgmax=800" width="582" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And this was right before the alien mothership appeared in the sky and started to lay waste to the city:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_cWdorEDEaNg/Sh170ASEuzI/AAAAAAAAAH0/vsMf7JxFBlI/s1600-h/IMG_6267%5B6%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="394" alt="IMG_6267" src="http://lh6.ggpht.com/_cWdorEDEaNg/Sh170jx2ZjI/AAAAAAAAAH4/fyQcuFZ1uoI/IMG_6267_thumb%5B4%5D.jpg?imgmax=800" width="588" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;PS: thanks to Stefan for letting me use his photos :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-967474568828017914?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/967474568828017914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=967474568828017914' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/967474568828017914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/967474568828017914'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/05/new-laboratory.html' title='New Laboratory'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_cWdorEDEaNg/Sh17x1qqqWI/AAAAAAAAAHg/EAdRSePSejI/s72-c/IMG_6187_thumb%5B7%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5207326137161423709</id><published>2009-05-23T21:22:00.001+01:00</published><updated>2009-05-23T21:26:32.098+01:00</updated><title type='text'>Another day with PSN</title><content type='html'>&lt;ol&gt;   &lt;li&gt;Read somewhere on the Internets that Infamous demo is on PSN.&lt;/li&gt;    &lt;li&gt;Turn on PS3.&lt;/li&gt;    &lt;li&gt;“A system update is available”.&lt;/li&gt;    &lt;li&gt;Stare for an eternity at a very slowly growing bar indicating not only the current download status but also my growing anger level.&lt;/li&gt;    &lt;li&gt;Stare for another eternity at another status bar which says that its installing the update or something… &lt;/li&gt;    &lt;li&gt;Contemplate how the PS3 feels more and more like a fucking IBM-PC connected to a 9600 baud analog modem.&lt;/li&gt;    &lt;li&gt;Finally! Hurry into the PSN shop, try to make sense of the confusing layout, until (after what feels like another eternity) it slowly dawns on me that the European shop (or German shop, or whatever other obscure region got the fist up its ass this time) does in fact NOT have the demo which (maybe) is only on the Japanese shop (or Americanese, or Papua-New-Guineaese, Kamerunese or whatever other region is lucky this time).&lt;/li&gt;    &lt;li&gt;Turn off the PS3 while shaking head in frustration thinking about how internet commerce ought to be the future and wipe out boxed products completely. Somebody should tell the bean counters and lawyers that the internet simply wasn’t designed with national borders in mind.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;It’s seldom enough that I feel like turning on my PS3, but being greeted with a fucking system update which takes forever to download (and install!) every single fucking time is a &lt;strong&gt;huge *&lt;/strong&gt;&lt;strong&gt;fucking*&lt;/strong&gt; &lt;strong&gt;TURNOFF&lt;/strong&gt;! At least on the PC, I can continue to do other things while Windows is updating.&lt;/p&gt;  &lt;p&gt;To be fair, Microsoft isn’t any worse when it comes to denying us Germans the good stuff, but at least I can check MajorNelsons webpage for the all-to-common “Not available in Germany” message before spending forever looking for the download on the Marketplace. And system updates are just not an issue on the 360. The last one (the NXE update) took under 2 minutes to download (and install, might I add), and unlike a typical PS3 system update, the changes are usually visible to the user.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5207326137161423709?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5207326137161423709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5207326137161423709' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5207326137161423709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5207326137161423709'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/05/another-day-with-psn.html' title='Another day with PSN'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4643094942545407067</id><published>2009-05-23T17:10:00.001+01:00</published><updated>2009-05-23T20:15:31.083+01:00</updated><title type='text'>Maya Programming #1</title><content type='html'>&lt;p&gt;[Edit: fixed some bugs in the MEL code]&lt;/p&gt;  &lt;p&gt;Maya is an incredibly complex beast, but it is also an incredibly powerful beast. The C++ API fully exposes this complexity to the outside (even more then the MEL API), and after about 10 years of working with the Maya SDK I still have some sort of love/hate relationship with the C++ API (and a thorough hate/hate relationship with MEL).&lt;/p&gt;  &lt;p&gt;Much of the complexity stems from the fact that even a simple Maya scene is a huge network of interconnected tiny nodes (the dependency graph), and while the API tries its best to provide shortcuts for finding the relevant data, one often has to write several (sometimes a lot) lines of code to get to the actually wanted piece of data. Typical Maya code (at least typical exporter-plugin code) often consists of cascades of calls to getters and iterators just to find and read a single data element from some object hidden deeply in the dependency graph. Things have gotten better over time though, almost every new Maya version provided shortcuts for getting typical data (like triangulated mesh geometry, vertex tangents, or the shader nodes connected to the polygons of a shape node). I think the Maya team needed a little while before they got a feel for the needs of the gaming industry. Since Maya has more of a movie industry background, and (at least in Europe) is still a bit exotic compared to its (ugly) step-brother 3DMax this is understandable.&lt;/p&gt;  &lt;p&gt;When programming a Maya plugin the actual API documentation is actually relatively useless because it’s mainly a pure class interface documentation and doesn’t explain how the objects of a Maya scene relate to each other or what’s the best practice to solve a specific task (and worse, there are often a lot of different ways to do something, and its up to the programmer to find the easiest, or cleanest, or fastest way). Instead of relying on the documentation its often better to explore the object relationships directly in Maya through the Script Editor, and only when one has a clear understanding of how the data is organized in Maya, lookup the API docs to find out how it’s done in C++.&lt;/p&gt;  &lt;p&gt;Before starting to explore a Maya scene through the script editor one only needs to understand this:&lt;/p&gt;  &lt;p&gt;The entire Maya scene is a single &lt;strong&gt;Dependency Graph&lt;/strong&gt;, which is built from &lt;strong&gt;Dependency Nodes&lt;/strong&gt; connected through &lt;strong&gt;Plugs &lt;/strong&gt;(think of it as a brain made of interconnected neurons). Every time the Maya user manipulates the scene he may add or remove nodes from the graph, connect or disconnect plugs, or feed some new data into some input plugs). After parts of the dependency graph have been manipulated, it is in a dirty state and must be brought uptodate before being displayed (or examined by an exporter plugin). But instead of evaluating the entire graph (which would be very slow in a complex Maya scene with thousands of nodes), only the dirty parts of the graph which actually need updating will be evaluated. This is where the dependency stuff comes into play: every dependency node depends only on the nodes connected to its input plugs. Only input plugs marked as “dirty” need to be evaluated. If some data is changed at one of the input plugs it will propagate its dirty state “upward” in the graph, and in turn an “evaluation wave” will propagate “downwards” through the dirty nodes.&lt;/p&gt;  &lt;p&gt;This system might seem overkill for simple 3D scenes, but as soon as animation, expressions and the construction history come into play it all makes sense, and its actually a very elegant design.&lt;/p&gt;  &lt;p&gt;Now lets go on with the exploration:&lt;/p&gt;  &lt;p&gt;Some important MEL commands for this are &lt;strong&gt;listAttrs&lt;/strong&gt;, &lt;strong&gt;getAttr, setAttr&lt;/strong&gt; and &lt;strong&gt;connectionInfo&lt;/strong&gt;. Let’s start with a simple illustration of a dependency chain.&lt;/p&gt;  &lt;p&gt;First open Maya’s script editor and create a polygon cube at the origin:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;polyCube&lt;/strong&gt; [Ctrl+Return]&lt;/p&gt;  &lt;p&gt;This creates a transform node, and a child shape node in Maya (pCube1 and polyCube1). Let’s list the attributes of the transform node (for the sake of simplicity… these are equivalent with plugs):&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;listAttr pCube1&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This produces dozens of attribute names (a first indication of how complex even a simple Maya scene is). Somewhere in this mess is the translateX attribute which defines the position on the X axis. Let’s have a look at its content:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;getAttr pCube1.translateX&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This should return 0, since we created the cube at the origin. Let’s move it to x=5.0:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;setAttr pCube1.translateX 5.0&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;When the command executes, the cube in the 3D view should jump to its new position.&lt;/p&gt;  &lt;p&gt;So far so good. Lets create a simple dependency by adding a transform animation. Just type this into Maya script editor (start a new line with Return, and execute the whole sequence with Ctrl+Return):&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;setKeyframe pCube1;      &lt;br /&gt;currentTime 10;       &lt;br /&gt;setAttr pCube1.translateX -5.0;       &lt;br /&gt;setKeyframe pCube1;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This sets an animation key at the current position (time should be 0 and the cube’s x position should be 5), then sets the current time to 10, moves the cube to x=-5 and sets another animation key.&lt;/p&gt;  &lt;p&gt;Now grab the time slider and move it between frame 0 and 10, the cube should now move on the X axis. Now lets try to read the translateX attribute at different points in time. Move the time slider to frame number 3 and execute:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;getAttr pCube1.translateX&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This should return 2.777778. Now move the time slider to frame 6 and get the same attribute:&lt;/p&gt;  &lt;p&gt;The result should now be –0.555556. The previously static attribute value now changes over time since we added an animation to the object. Obviously some other node manipulates the translateX attribute on pCube1 whenever the current time changes. Let’s see who it is:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;connectionInfo -sourceFromDestination pCube1.translateX&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This yields: pCube1_translateX.output&lt;/p&gt;  &lt;p&gt;So there’s an object called&lt;strong&gt; pCube1_translateX&lt;/strong&gt;, which has a plug called &lt;strong&gt;output&lt;/strong&gt;, which feeds the translateX attribute of our cube with data. Now let’s check what type of object this pCube1_translateX is:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;nodeType pCube1_translateX&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The result: animCurveTL.&lt;/p&gt;  &lt;p&gt;Now let’s check what the docs say about this node type. Open the Maya docs, go to “Technical Documentation –&amp;gt; Nodes”, and type animCurveTL into the “By substring” search box. This is what comes up:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;This node is an &amp;quot;animCurve&amp;quot; that takes an attribute of type &amp;quot;time&amp;quot; as input and has an output attribute of type &amp;quot;distance&amp;quot;. If the input attribute is not connected, it has an implicit connection to the Dependency Graph time node.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Interesting! Let’s double check: If the output plug of the animation curve is connected to the translateX attribute, it should return the same value for a specific time… Moving the time slider to frame 3 should yield a value of 2.77778, and indeed, a &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;getAttr pCube1_translateX.output&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;returns the expected value.&lt;/p&gt;  &lt;p&gt;Now lets try something crazy: what if we feed the current value of translateX into the translateZ attribute of our cube and thus make the dependency chain a bit more interesting? The result should be that the cube moves diagonally when the time slider is moved even though only the translateX attribute is animated by an animation curve:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;connectAttr -force pCube1.translateX pCube1.translateZ&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Now I cheated a bit by using the –force argument. The translateZ attribute was already automatically connected to another animation curve when we executed the setKeyframe command (same thing that happened for our translateX attribute), we need to break this connection before connecting to another plug, and the –force just does that.&lt;/p&gt;  &lt;p&gt;Lets see if it works by moving the time slider. And indeed… the cube moves diagonally on the X/Z plane as expected. Cool shit.&lt;/p&gt;  &lt;p&gt;So that’s it. That’s how everything in Maya works. The only difference to a really complex scene is that there are hundreds or thousands of dependency nodes connected through even more plugs.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4643094942545407067?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4643094942545407067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4643094942545407067' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4643094942545407067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4643094942545407067'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/05/maya-programming-1.html' title='Maya Programming #1'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6481493063077139670</id><published>2009-05-21T15:39:00.001+01:00</published><updated>2009-05-23T14:55:15.517+01:00</updated><title type='text'>Maya Plugin</title><content type='html'>&lt;p&gt;[Edit: I added some clarification to the “cleanup” point&amp;#160; below]&lt;/p&gt;  &lt;p&gt;I have started to write a new Maya plugin for Nebula3, which eventually may replace all (or parts of) our current plugin. The actual Maya plugin is only one small part of our asset pipeline, so this is not about rewriting the entire asset pipeline, just replacing one small gear in it. Otherwise it would be a truly Herculean task. In the beginning this will just be a private endeavour, free from time- or budget-limitations, so that no design compromises have to be made. This approach worked quite well for Nebula3 so it makes sense to use it more often in the future.&lt;/p&gt;  &lt;p&gt;Our current Maya plugin is stable and fast, but at least the C++ part of it is beginning to show its age, it’s becoming harder to maintain, and since it’s based on Nebula2 code it is a lot harder to do low-level things like file io compared to similar Nebula3 code.&lt;/p&gt;  &lt;p&gt;The new plugin will realize ideas I’ve been carrying around in the back of my head for quite some time, and which would be hard to implement into the existing plugin without a complete rewrite. The most important one is:&lt;/p&gt;  &lt;h5&gt;&lt;strong&gt;Separation into a platform-agnostic front-end and several specialized back-ends:&lt;/strong&gt;&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;The actual Maya plugin will export into intermediate file formats which are completely platform-independent (and probably even somewhat engine-independent). Thus the plugin itself becomes more of a generic 3D engine exporter tool which doesn’t have to change every time a new target platform is supported or an engine feature is added or rewritten. &lt;/li&gt;    &lt;li&gt;The back-end tools (or libs) convert the intermediate files into the files actually loaded by Nebula3. Those files can (and should) be highly platform-specific. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’m expecting that the larger chunk of code goes into the platform-agnostic plugin, and that the back-ends are relatively small and straight-forward. The main advantage of this separation is better maintainability. The core plugin can remain relatively stable and clean, while the back-ends can have a higher frequency of change, and the “throw-away-and-rewrite” barrier is a lot lower since only the relatively small back-end-code has to be replaced without affecting the core plugin and the other platform-back-ends (too much). Also, the platform-mini-teams have more freedom to implement platform-specific optimizations into their engine-ports, since they have complete control over their exporter-backend.&lt;/p&gt;  &lt;p&gt;The main disadvantage is that the export times will probably be a bit higher then now. A LOT of effort has gone into optimizing the performance of our toolkit plugin (exporting a scene with hundreds of thousands of polygon should only take up to a few seconds), and writing an additional set of output files may effect performance quite drastically. I’m planning to use XML only for the intermediate object hierarchy structure (which depends on the material complexity of the scene, but shouldn’t be more then a few dozen to a few hundred lines for a typical object), and to use binary file formats for “large stuff” like mesh and animation data. But if the XML files are hindering io performance too much, I will clearly go to a performance-optimized binary format, even if human-readability would be a major plus there (in the end, one set of the back-end tools could convert to human-readable ASCII file formats).&lt;/p&gt;  &lt;p&gt;If you’re wondering why performance is so critical during export: consider that a project has about ten-thousand 3d models to be exported (which isn’t unrealistic for a complex RPG project like Drakensang for example). If the export time can be reduced by only one second per object, the time for a complete rebuild will be reduced by almost 3 hours! Actually, most 3d models batch-export in much less then 1 second in our build-pipeline, it’s the texture-conversion to DDS which eats the most build-time…&lt;/p&gt;  &lt;p&gt;There are a lot of other things a Maya exporter tool should do right to be considered well-mannered:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;It should support batch-exporting and automation (command-line batch-exporters, means of controlling export parameters on thousand of assets, standardized project directory structures, etc…). &lt;/li&gt;    &lt;li&gt;It should be designed for a multi-project environment (a modeling artist or level designer must be able to quickly switch from one project to another). &lt;/li&gt;    &lt;li&gt;It should of course offer a fast and exact preview for immediate quality control (the artist should be able to get an in-engine view of his work immediately) &lt;/li&gt;    &lt;li&gt;It should not force artists to use archaic file formats. For instance, all texture conversion tools for the various console platforms I have encountered so far only accept crap like TGA or BMP as input, but NOT the industry standard PSD format! Quite baffling if one thinks about it. I don’t know how other companies deal with this, but I think it’s quite unacceptable to keep an extra TGA version for every one of tens-of-thousands textures around, just so that the batch exporter tools will work (for the console platforms we wrote our own wrappers, which first convert a PSD file to a temp TGA file and then invoke the conversion tools coming with the SDKs, but this is REALLY bad for the batch-export performance of course). &lt;/li&gt;    &lt;li&gt;It should be fault-tolerant: Maya is an incredibly complex piece of technology, and plugins usually have no other chance then only supporting a specific subset of its features. The plugin should not crash or stop working when it encounters something slightly wrong or unknown in the Maya scene, instead it should provide the artist with clear warnings and readable error messages. &lt;/li&gt;    &lt;li&gt;It should not require too many restrictions in the Maya scene: for instance, a very early version of our exporter tools required the artist to manually triangulate the scene, which is unacceptable of course. &lt;/li&gt;    &lt;li&gt;It should cleanup the Maya scene during export: It’s relatively easy in Maya to create zero-area faces, or duplicate faces, or faces with a zero UV-area, etc... The exporter should remove those artefacts, and in those cases where an automatic handling is not possible, provide a detailed error log to the artist so that he has enough information to remove those problems manually. [EDIT: this was badly worded… of course the plugin should not modify the actual Maya scene, but instead remove artefacts from the data which has already been extracted from the Maya scene… it’s a bad idea to modify the Maya scene itself during export!]&lt;/li&gt;    &lt;li&gt;It should optimize the Maya scene during export: For instance, the last time I looked at the XNA Maya plugin it exported a single material group for every Maya shape node, resulting in hundreds of draw calls for our simple Tiger tank example object. This is almost as bad as requiring the artist to work with a triangulated scene. Instead the plugin should try its best to optimize the scene for efficient rendering during export (like grouping polygons by material, sorting vertices for efficient vertex-cache usage, removing redundant vertices, and so on). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Of course this list could go on for a few more dozen points, there’s almost 10 years of work in our asset pipeline, and there’s probably more C++ and MEL code in it then in Nebula3 (which isn’t necessarily a good thing ;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6481493063077139670?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6481493063077139670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6481493063077139670' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6481493063077139670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6481493063077139670'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/05/maya-plugin.html' title='Maya Plugin'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-740557547550008192</id><published>2009-04-15T15:36:00.001+01:00</published><updated>2009-04-15T15:36:49.872+01:00</updated><title type='text'>N3 SDK Apr 2009 download</title><content type='html'>&lt;p&gt;Here's the new SDK (see previous post), I hope releases will be a little more frequent in the future. As always, source code for the Xbox360 or Wii versions is not included for obvious legal reasons.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.radonlabs.de/internal/N3SDK_Apr2009.exe" href="http://www.radonlabs.de/internal/N3SDK_Apr2009.exe"&gt;http://www.radonlabs.de/internal/N3SDK_Apr2009.exe&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Have fun!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-740557547550008192?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/740557547550008192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=740557547550008192' title='25 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/740557547550008192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/740557547550008192'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/04/n3-sdk-apr-2009-download.html' title='N3 SDK Apr 2009 download'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>25</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6994811407489212567</id><published>2009-04-14T19:03:00.001+01:00</published><updated>2009-04-14T19:16:57.538+01:00</updated><title type='text'>New N3 SDK (Apr 2009)</title><content type='html'>&lt;p&gt;The new SDK release should be ready by tomorrow (unless there's some last-minute fuckup). For now here's a rough What's New list since the last SDK from September 2008:&lt;/p&gt;  &lt;h5&gt;Tools:&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;new command line tool: archiver3 - multiplatform wrapper for generating file archives&lt;/li&gt;    &lt;li&gt;new command line tool: n2converter3 - convert .n2 files to .n3 files (Nebula graphics objects)&lt;/li&gt;    &lt;li&gt;new command line tool: suiconverter3 - batch converter for SUI resources (simple user interface), currently only useful for the Wii port&lt;/li&gt;    &lt;li&gt;new command line tool: synctool3 - sync local project directory from build server (only useful with our inhouse asset pipeline)&lt;/li&gt;    &lt;li&gt;new command line tool: countlines3 - count N3 source code lines and generate Excel-compatible csv-file (comma separated values)&lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;Foundation Layer:&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;brought Wii port uptodate (not part of the public SDK of course)&lt;/li&gt;    &lt;li&gt;Util::CmdLineArgs renamed to Util::CommandLineArgs&lt;/li&gt;    &lt;li&gt;Scripting subsystem moved into an addon&lt;/li&gt;    &lt;li&gt;Remote subsystem moved into an addon&lt;/li&gt;    &lt;li&gt;new Macros __ConstructInterfaceSingleton / __DestructInterfaceSingleton&lt;/li&gt;    &lt;li&gt;new standard define __MAYA__ if compiled as part of a Maya plugin&lt;/li&gt;    &lt;li&gt;new concept: ExitHandlers (see Core::ExitHandler)&lt;/li&gt;    &lt;li&gt;new low level debug feedback method Core::SysFunc::MessageBox()&lt;/li&gt;    &lt;li&gt;new concept &amp;quot;root directory&amp;quot; (see CoreServer::SetRootDirectory)&lt;/li&gt;    &lt;li&gt;various changes to enable using N3 code in N2/Mangalore apps (N2 now sits on top of a very slim N3 Foundation layer)&lt;/li&gt;    &lt;li&gt;SizeT and IndexT now signed (had to be done for N2/Mangalore compatibility unfortunately)&lt;/li&gt;    &lt;li&gt;IO::Console is now an InterfaceSingleton&lt;/li&gt;    &lt;li&gt;various debug HTML page handlers can now sort table content by columns&lt;/li&gt;    &lt;li&gt;Debug::DebugServer is now an InterfaceSingleton&lt;/li&gt;    &lt;li&gt;added a minimal Debug::HelloWorldRequestHandler as example for a simple HttpRequestHandler&lt;/li&gt;    &lt;li&gt;new comfort method Http::HtmlPageWriter::TableRow2(), saves code when creating a 2-column HTML table&lt;/li&gt;    &lt;li&gt;added Http::HttpClient class, allows send requests to HTTP servers&lt;/li&gt;    &lt;li&gt;Http::HttpInterface is now an InterfaceSingleton and derived from Interface::InterfaceBase&lt;/li&gt;    &lt;li&gt;new class Http::HttpRequestWriter&lt;/li&gt;    &lt;li&gt;new class Http::HttpResponseReader&lt;/li&gt;    &lt;li&gt;added a &amp;quot;single thread mode&amp;quot; to HttpServer&lt;/li&gt;    &lt;li&gt;added new classes InterfaceBase and InterfaceHandlerBase&lt;/li&gt;    &lt;li&gt;moved IOInterface-stuff under IO&lt;/li&gt;    &lt;li&gt;new class Debug::ConsolePageHandler, displays console output in web server&lt;/li&gt;    &lt;li&gt;generalized Zip filesystem stuff into general archive filesystem, with ZIP support as one specialization (on Wii, ARC files are used instead)&lt;/li&gt;    &lt;li&gt;ZipFileSystem is now an InterfaceSingleton (no more per-thread wasted memory for archive table-of-contents)&lt;/li&gt;    &lt;li&gt;added an &amp;quot;AsString()&amp;quot; method to IO::FileTime&lt;/li&gt;    &lt;li&gt;new methods in Win360FSWrapper: SetFileWriteTime(), GetAppDataDirectory(), GetProgramsDirectory()&lt;/li&gt;    &lt;li&gt;moved IO::ZipFileStream class to io/zipfs&lt;/li&gt;    &lt;li&gt;moved path assign methods from IoServer into new InterfaceSingleton: IO::AssignRegistry&lt;/li&gt;    &lt;li&gt;new standard assigns under Windows: &amp;quot;appdata&amp;quot; and &amp;quot;programs&amp;quot;, mainly useful for tools&lt;/li&gt;    &lt;li&gt;bugfix in IO::ExcelXmlReader for tables with empty cells&lt;/li&gt;    &lt;li&gt;new class IO::HistoryConsoleHandler, captures console output into a ring buffer (used by Debug::ConsolePageHandler)&lt;/li&gt;    &lt;li&gt;moved URI scheme methods from IoServer into IO::SchemeRegistry InterfaceSingleton&lt;/li&gt;    &lt;li&gt;removed critical section from Stream::Open / Stream::Close&lt;/li&gt;    &lt;li&gt;new method: IO::XmlWriter::WriteComment()&lt;/li&gt;    &lt;li&gt;new methods specialized float4-loading methods: Math::float4::load_float3(), Math::float4::load_ubyte4n_signed()&lt;/li&gt;    &lt;li&gt;vector comparison methods in Math::float4 more intuitive and flexible&lt;/li&gt;    &lt;li&gt;Math::matrix44() default constructor now sets object to the identity matrix (default constructor still empty in Math::float4!)&lt;/li&gt;    &lt;li&gt;new constructor from float4 in Math::quaternion&lt;/li&gt;    &lt;li&gt;moved lots of math functions from scalar.h to platform-specific d3dx9_scalar.h to enable platform-specific optimizations&lt;/li&gt;    &lt;li&gt;Memory::Heap constructor now accepts initial and maximum heap size&lt;/li&gt;    &lt;li&gt;memory leap detection for Memory::Heap (doesn't quite work as expected yet)&lt;/li&gt;    &lt;li&gt;removed global heaps: SmallBlockHeap, LargeBlockHeap, StringHeap&lt;/li&gt;    &lt;li&gt;added global heaps: PhysicsHeap, AppHeap, StringObjectHeap, StringDataHeap&lt;/li&gt;    &lt;li&gt;new experimental Win360MemoryPoolClass &lt;/li&gt;    &lt;li&gt;Messaging::AsyncPort: can now add message handlers to already opened ports&lt;/li&gt;    &lt;li&gt;added &amp;quot;deferred handled&amp;quot; flag to Messaging::Message (used in the rendering thread to keep CreateEntity messages around until their resources are loaded)&lt;/li&gt;    &lt;li&gt;wrapped socket and TCP/IP classes to enable &amp;quot;TCP/IP-over-HIO2-Tunneling&amp;quot; on the Wii&lt;/li&gt;    &lt;li&gt;System::Win32Registry(): split Read() method into ReadString() and ReadInt()&lt;/li&gt;    &lt;li&gt;System::ByteOrder::Convert&amp;lt;TYPE&amp;gt;() methods now return a value, added new methods System::ByteOrder::ConvertInPlace&amp;lt;TYPE&amp;gt;()&lt;/li&gt;    &lt;li&gt;new methods Threading::Interlocked::Exchange() and CompareExchange()&lt;/li&gt;    &lt;li&gt;Win360Thread::IsRunning() now uses the Win32 function GetExitCodeThread() to detect whether the thread is running&lt;/li&gt;    &lt;li&gt;new method Threading::Thread::YieldThread() (gives up time-slice)&lt;/li&gt;    &lt;li&gt;new class Threading::SafeFlag&lt;/li&gt;    &lt;li&gt;new concept: Timing::MasterTime and Timing::SlaveTime, main thread has a MasterTime object, and distributes &amp;quot;main time&amp;quot; to slave threads (i.e. the render thread)&lt;/li&gt;    &lt;li&gt;Util::Array now has a MinGrowSize and MaxGrowSize to prevent excessive memory waste for huge arrays&lt;/li&gt;    &lt;li&gt;new experimental class Util::Delegate (doesn't work in Codewarrior unfortunately)&lt;/li&gt;    &lt;li&gt;new method Util::FixedArray::AsArray()&lt;/li&gt;    &lt;li&gt;new methods Util::Dictionary::KeysAs&amp;lt;TYPE&amp;gt;(), and Util::Dictionary::ValuesAs&amp;lt;TYPE&amp;gt;()&lt;/li&gt;    &lt;li&gt;new class Util::PriorityArray (which actually isn't needed anymore I think)&lt;/li&gt;    &lt;li&gt;new class Util::RandomNumberTable&lt;/li&gt;    &lt;li&gt;new class Util::Round&lt;/li&gt;    &lt;li&gt;made many non-essential Util::String methods non-inline &lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;Render Layer&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;new Character subsystem (modular character rendering, fresh rewrite of N2's Character3 system)&lt;/li&gt;    &lt;li&gt;new CoreFX subsystem (ported from Mangalore's VFX subsystem (visual effects)) -&amp;gt; NOTE: will be moved into addon&lt;/li&gt;    &lt;li&gt;new CoreUI and UI subsystems (simple user interface system) -&amp;gt; NOTE: will be moved into addon &lt;/li&gt;    &lt;li&gt;new Video subsystem (video playback, currently Xbox360 only) -&amp;gt; NOTE: will be moved into addon&lt;/li&gt;    &lt;li&gt;new Particles subsystem (rewritten from scratch) -&amp;gt; NOTE: will be moved into addon&lt;/li&gt;    &lt;li&gt;new PostEffect subsystem (ported from Mangalore) -&amp;gt; NOTE: will be moved into addon&lt;/li&gt;    &lt;li&gt;new Vibration subsystem (game pad vibration support) -&amp;gt; NOTE: will be moved into addon&lt;/li&gt;    &lt;li&gt;new Vegetation subsystem (Drakensang's grass renderer, currently broken under N3) -&amp;gt; NOTE: will be moved into addon&lt;/li&gt;    &lt;li&gt;new concept: RenderModules, clean framework to add functionality to the render thread&lt;/li&gt;    &lt;li&gt;new concept: AnimEvents, animations can emit events at certain sample times (i.e. for playing foot-step sounds at the right time)&lt;/li&gt;    &lt;li&gt;new concept: character attachments (swords, etc...)&lt;/li&gt;    &lt;li&gt;lots of bugfixes and improvements to Animation system&lt;/li&gt;    &lt;li&gt;new concept: AnimDrivenMotion, synchronize character movement with its current animation&lt;/li&gt;    &lt;li&gt;new concept: batched messages, drastically reduce communication overhead between threads by client-side batching of messages&lt;/li&gt;    &lt;li&gt;new methods: Audio::AudioEmitter::Pause() and Resume()&lt;/li&gt;    &lt;li&gt;new methods: AudioDevice::SetGlobalVariable() / GetGlobalVariable()&lt;/li&gt;    &lt;li&gt;added/fixed Xbox360 support to XACT audio classes&lt;/li&gt;    &lt;li&gt;new class: MultipleRenderTarget, wraps MRT rendering&lt;/li&gt;    &lt;li&gt;new class: MouseRenderDevice (currently only implemented on Wii)&lt;/li&gt;    &lt;li&gt;added support for GPU-instanced-rendering &lt;/li&gt;    &lt;li&gt;RenderTarget: added support to resolve depth buffer into texture (Xbox360 only)&lt;/li&gt;    &lt;li&gt;RenderTarget: added support to create a resolve-texture which can be efficiently read by the CPU&lt;/li&gt;    &lt;li&gt;added &amp;quot;late-binding&amp;quot; to ShaderVariableInstance&lt;/li&gt;    &lt;li&gt;D3D9StreamTextureLoader and D3D9Texture moved from win360 to d3d9, since specialized Xbox360 versions exist now&lt;/li&gt;    &lt;li&gt;Debug::MeshPageHandler can now display a dump of the vertex data in the web browser&lt;/li&gt;    &lt;li&gt;Debug::TexturePageHandler now displays the current resource state of textures (Initial, Pending, Loaded, etc...)&lt;/li&gt;    &lt;li&gt;new class CoreGraphics::MemoryMeshLoader&lt;/li&gt;    &lt;li&gt;renamed CoreGraphics::Shape to CoreGraphics::RenderShape (because of CodeWarrior problems with identical filenames in different directories)&lt;/li&gt;    &lt;li&gt;added Multiple Render Target support to Frame::FramePass and Frame::FramePostEffect&lt;/li&gt;    &lt;li&gt;Graphics::Display::GetDisplayMode() now returns display mode actually set by the CoreGraphics::DisplayDevice (may differ from the requested display mode)&lt;/li&gt;    &lt;li&gt;Graphics::GlobalLightEntity: all light parameter changes are now transferred to the render-thread-side post-creation&lt;/li&gt;    &lt;li&gt;Graphics::GraphicsEntity: internal entity handle now only becomes valid after resources have been loaded on the render-thread-side&lt;/li&gt;    &lt;li&gt;Graphics::GraphicsInterface now uses batch messaging to communicate with render-thread (only 1 message sent per frame)&lt;/li&gt;    &lt;li&gt;Graphics::Handle is now a smart pointer (fixes problems where render-thread graphics entities were disposed too early)&lt;/li&gt;    &lt;li&gt;Graphics::ModelEntity: support for AnimDrivenMotion&lt;/li&gt;    &lt;li&gt;new Input::GamePad methods: ButtonAsString(), AxisAsString(), GetStateAsInputEvents()&lt;/li&gt;    &lt;li&gt;InternalGraphicsEntities are now registered with the InternalGraphicsServer&lt;/li&gt;    &lt;li&gt;lots of changes in InternalGraphicsServer and InternalModelEntity which require a proper cleanup doh&lt;/li&gt;    &lt;li&gt;added support for 2-sided lighting to global lights&lt;/li&gt;    &lt;li&gt;new classes: Models::AnimatorNode and Models::AnimatorNodeInstance (legacy Nebula2 stuff)&lt;/li&gt;    &lt;li&gt;new classes: Models::CharacterNode and Models::CharacterNodeInstance, integrate character rendering with model nodes&lt;/li&gt;    &lt;li&gt;loading of ModelNodes completely rewritten (new .n3 file format, plus n2converter3 tool to convert .n2 files to .n3)&lt;/li&gt;    &lt;li&gt;new Model::OnResourcesLoaded() method, if Model subclasses need to do initialization work after resources have finished loading&lt;/li&gt;    &lt;li&gt;new methods to lookup ModelNodeInstances on ModelInstances&lt;/li&gt;    &lt;li&gt;new class Models::StreamModelLoader&lt;/li&gt;    &lt;li&gt;lots of other minor changes in namespace Models&lt;/li&gt;    &lt;li&gt;new class: RenderUtil::MouseRayUtil, convert 2D mouse position into world-space 3D-ray&lt;/li&gt;    &lt;li&gt;new method: ResourceManager::CheckPendingResources(), returns true when there are currently no pending resources waiting to be loaded&lt;/li&gt;    &lt;li&gt;SharedResourceServer: several methods now accept a ResourceLoader object when creating shared resources &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I also did some interesting line counting statistics recently for the Foundation and Render layers (hopefully the images won't be scaled down too much):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_cWdorEDEaNg/SeTTFLBjBtI/AAAAAAAAAHA/MItj3LLpJC0/s1600-h/foundation_layer%5B8%5D.gif"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="416" alt="foundation_layer" src="http://lh4.ggpht.com/_cWdorEDEaNg/SeTP6v7Fk_I/AAAAAAAAAHE/qHHcRb8olKo/foundation_layer_thumb%5B6%5D.gif?imgmax=800" width="640" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_cWdorEDEaNg/SeTP60dpOdI/AAAAAAAAAHI/MJGdhnZwcTY/s1600-h/render_layer%5B5%5D.gif"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="416" alt="render_layer" src="http://lh4.ggpht.com/_cWdorEDEaNg/SeTP7nA18oI/AAAAAAAAAHM/izdjQMhBAbw/render_layer_thumb%5B3%5D.gif?imgmax=800" width="640" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;quot;General&amp;quot; is the platform-agnostic code, which is the same for all platforms, &amp;quot;Win360&amp;quot; is the code which is identical between Win32 and Xbox360. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6994811407489212567?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6994811407489212567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6994811407489212567' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6994811407489212567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6994811407489212567'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/04/new-n3-sdk-apr-2009.html' title='New N3 SDK (Apr 2009)'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_cWdorEDEaNg/SeTP6v7Fk_I/AAAAAAAAAHE/qHHcRb8olKo/s72-c/foundation_layer_thumb%5B6%5D.gif?imgmax=800' height='72' width='72'/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4718233500519733313</id><published>2009-04-04T15:38:00.001+01:00</published><updated>2009-04-04T15:54:07.750+01:00</updated><title type='text'>Still Alive</title><content type='html'>&lt;p&gt;Just a quick update, since I haven’t posted for a while:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I’ve pretty much gone into hermit mode for the whole of March with 10 hour-days and six-day-weeks at the Labs because of an interesting new project. Pretty much everything I did falls under NDA unfortunately, so there wasn’t anything I could write about anyway… so that’s my half-assed apology for not posting anything. Although I must admit that it was quite relaxing to simply cut-off all non-essential communication and social contacts and just concentrate on the task at hand, almost feels like I just came back from a long vacation, even though I’m a bit exhausted physically ;)&lt;/li&gt;    &lt;li&gt;The &lt;a href="http://www.ddj.com/architect/216402188?pgno=1" target="_blank"&gt;Larrabee instruction set&lt;/a&gt; looks damn impressive, but I’ll withhold my enthusiasm until it’s actually available and doesn’t turn out to be just another fucking “onboard graphics chip”.&lt;/li&gt;    &lt;li&gt;Same for OnLive. Don’t have tech-journalists any fucking common sense to hype this shit up instead of looking behind the curtain? Even Xbox Live (the current Gold Standard) takes a nose-dive from time to time when a popular multiplayer game is released, and that’s just doing match-making over its servers with (probably) a few Kbytes of traffic per session. Maybe OnLive is capable to demonstrate a system which scales up to a million simultaneous players spread across the globe, running a taxing 3D game with “acceptable” lag and image quality. If that happens I would be truly impressed. I predict that OnLive will collect a considerable amount of money from eager investors (who seem to believe that little nuisances like the Laws Of Nature can be dealt with by throwing the right amount of money at them), waste that money over the next few years, while tech demonstrations become less and less impressive (even though they’ll be fabricated), and finally, if said investors are lucky, maybe one or two worthless patents and “yet another” video codec come out of the whole venture. It’s Phantom all over again.&lt;/li&gt;    &lt;li&gt;Drakensang won the new “German Computer Game Award” for “Best German Game” and “Best Youth Game”. Please excuse this uncommon display of enthusiasm, but let me just say: Yay!&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I love &lt;strong&gt;Resident Evil 5&lt;/strong&gt;. Capcom are my official kings of next-gen. Funny thing is: I almost skipped the game because of the demo. I haven’t played any previous RE’s (at that time I hadn’t converted to the dark side of console gaming yet), so I was completely put off by the strange “tank controls”. Also, the demo took place in “generic Middle-Eastern/North-African town”) which I already know well enough from COD4, MGS4 and FarCry2. No-but-thank-you.&lt;/p&gt;  &lt;p&gt;But the actual game… I’d almost go as far to say that this is the best game of this console generation. The only little imperfection are those controls, but it took me only an hour or so to not even think about them anymore and use them just as automatically as the GeOW, or COD, or Rainbow Six controls. They are different from the “standard FPS controls”, but that’s the point, they are just &lt;strong&gt;different&lt;/strong&gt; then the others, but with a little practice just as easy and intuitive in their own way. &lt;/p&gt;  &lt;p&gt;The pacing of the game, the location design (there are some really breathtaking locations after “Generic Town”), the sound track, the story-telling, the characters, the cutscenes, the BOSS-FIGHTS (OMG the bosses are epic) – the way how coop-gameplay is implemented – everything is absolutely perfect. And RE5 is a console game through and through, not some FPS with more or less obvious PC heritage like COD or Gears. Little things like the “persistent inventory”, the massive amount of unlockables, the NewGame+ and Mercenary mode - every little bit of RE5 feels, tastes and smells like a 100% pure next-gen console game. Alright that’s it, I need to go play some RE5 now. Bye.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4718233500519733313?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4718233500519733313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4718233500519733313' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4718233500519733313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4718233500519733313'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/04/still-alive.html' title='Still Alive'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-8218539861956165413</id><published>2009-02-23T20:25:00.001+01:00</published><updated>2009-02-23T20:25:36.760+01:00</updated><title type='text'>Bullshit Paradise</title><content type='html'>&lt;p&gt;Dammit, what’s that EA-login bullshit in Burnout Paradise? Didn’t they get the memo from Konami? Turns out my usual email address for shit like this at &lt;a href="mailto:fuck@you.com"&gt;fuck@you.com&lt;/a&gt; was already taken by somebody else, oh well… Crap like this should be prohibited by Microsoft’s certification process, it’s completely working against the whole idea of Xbox Live.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-8218539861956165413?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/8218539861956165413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=8218539861956165413' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8218539861956165413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8218539861956165413'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/02/bullshit-paradise.html' title='Bullshit Paradise'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3201187180847297586</id><published>2009-02-21T14:34:00.002+01:00</published><updated>2009-02-21T15:19:22.064+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>N3’s Game Database Structure</title><content type='html'>&lt;p&gt;Here’s some info on the game database structure used by N3 and N2’s Mangalore, which might be helpful for level editor tools.&lt;/p&gt;  &lt;p&gt;“Game data” basically means “everything except graphics, audio or movie stuff”.&lt;/p&gt;  &lt;p&gt;All Nebula game-data lives in 2 SQLite database files:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;home:export/db/static.db4:&lt;/strong&gt; This contains all “static” data which doesn’t change over the course of a game session.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;home:export/db/game.db4:&lt;/strong&gt; This contains all the data which may change during a game session.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Those files can be inspected and modified with the &lt;a href="http://www.google.de/search?q=SQLiteSpy" target="_blank"&gt;SQLiteSpy&lt;/a&gt; tool, but since some of the contained data are blobs it may be a good idea to access them with custom tools (N3’s db addon offers wrapper classes for this, but of course it’s also possible to use sqlite directly to access the database).&lt;/p&gt;  &lt;p&gt;Both database files are normally populated by various exporter tools in our inhouse-asset-pipeline. &lt;/p&gt;  &lt;p&gt;The game.db4 file is important for N3’s standardized &lt;strong&gt;NewGame/Continue/Save/Load&lt;/strong&gt; feature:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;on &lt;strong&gt;New Game&lt;/strong&gt;, game.db4 will be copied to the user: directory of the application, changes during game play will be committed back to this copy (usually when a level is left)&lt;/li&gt;    &lt;li&gt;on &lt;strong&gt;Continue Game&lt;/strong&gt;, N3 will simply open the existing game.db4 file under “user:”&lt;/li&gt;    &lt;li&gt;on &lt;strong&gt;Save Game&lt;/strong&gt;, a copy of the game.db4 file under “user:” will be performed into the save-game directory&lt;/li&gt;    &lt;li&gt;on &lt;strong&gt;Load Game&lt;/strong&gt;, the game.db4 in “user:” will be overwritten with a copy from the save-game directory&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The main chunk of data in both database files are game entity related. A game entity is completely described by a collection of key/value pairs called attributes, which live in a single row of a database table.&lt;/p&gt;  &lt;p&gt;Application layer subsystems may store additional data in the database by managing their own tables in both databases. Usually, save-game relevant data lives in the game.db4 database, while read-only data lives in the static.db4 database file. Those custom-tables are usually read/written by derived Manager::OnLoad() and Manager::OnSave() methods.&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;static.db4&lt;/strong&gt; database contains at least the following tables:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;_Attributes:&lt;/strong&gt; This table contains a description of all attribute types used in other database tables. This lets an application load a database in a meaningful way even if the attributes haven’t been defined in its C++ code. The columns of _Attribute are:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;AttrName (string, primary, unique, indexed):&lt;/strong&gt; the attributes name, doh&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;AttrType (string):&lt;/strong&gt; the type of the attribute, this is how the different types are stored in the database:&lt;/li&gt;      &lt;ul&gt;       &lt;li&gt;&lt;strong&gt;int:&lt;/strong&gt; stored as SQL type INTEGER&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;bool:&lt;/strong&gt; stored as SQL type INTEGER&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;float:&lt;/strong&gt; stored as SQL type REAL&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;string: &lt;/strong&gt;stored as SQL type TEXT&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;vector3: &lt;/strong&gt;a float[3] stored as SQL type BLOB &lt;/li&gt;        &lt;li&gt;&lt;strong&gt;vector4: &lt;/strong&gt;a float[4] stored as SQL type BLOB (a raw Math::float4 written to the database)&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;matrix44: &lt;/strong&gt;a float[16] stored as SQL type BLOB (a raw Math::matrix44 written to the database)&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;guid: &lt;/strong&gt;a ubyte[16] stored as SQL type BLOB (result of Util::Guid::AsBinary())&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;blob:&lt;/strong&gt; can be used to efficiently store “anything else” in the database, hardly used though, Drakensang uses this to store the fog-of-war data for instance&lt;/li&gt;     &lt;/ul&gt;      &lt;li&gt;&lt;strong&gt;AttrReadWrite (bool), AttrDynamic (bool):&lt;/strong&gt; these two columns are currently not used in any meaningful way&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;&lt;strong&gt;_Categories:&lt;/strong&gt; Contains a description of every entity category which shows up in the database. This is basically the lookup-table for the CategoryManager. The _Categories table has the following columns:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;CategoryName (string, primary, unique, indexed): &lt;/strong&gt;The name of the category (e.g. Camera, NPC, Actor, Monster, etc…). Some category names are hard-coded and standardized across games:&lt;/li&gt;      &lt;ul&gt;       &lt;li&gt;&lt;strong&gt;Light:&lt;/strong&gt; describes level light sources&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;_Environment: &lt;/strong&gt;describes “environment objects”, these are simple graphics objects which don’t have game-play functionality&lt;/li&gt;        &lt;li&gt;&lt;strong&gt;Levels:&lt;/strong&gt; a meta-table which contains one row for every level in the game&lt;/li&gt;     &lt;/ul&gt;      &lt;li&gt;&lt;strong&gt;IsVirtualCategory (bool, indexed):&lt;/strong&gt; a virtual category only has a ‘template table’ but no ‘instance table’, virtual categories can be used to provide read-only data (lookup tables, etc) to the game application without having to write a custom exporter tool&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;IsSpecialCategory (bool, indexed): &lt;/strong&gt;only the above mentioned hard-coded categories are marked as “special”&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;CategoryTemplateTable (string):&lt;/strong&gt; The name of the database table with entity templates, a template table contains “blueprints” for entities with their initial attribute values. The method FactoryManager::CreateEntityByTemplate() is used to instantiate a new entity from such a template. Template tables live in the static.db4 database.&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;CategoryInstanceTable (string):&lt;/strong&gt; The name of the instance table (only if this is not a virtual category). Instance tables live in the game.db4 database file and contain one row per actual game entity. &lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;&lt;strong&gt;Template tables: &lt;/strong&gt;Template tables contain blueprint for entities which are created through the FactoryManager::CreateEntityByTemplate() method. A row in the template table contains the starting attribute values for a new entity of that type. A template table must contain at least the &lt;strong&gt;Id&lt;/strong&gt; column, which must be &lt;strong&gt;(string, primary, unique, indexed)&lt;/strong&gt;.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The &lt;strong&gt;game.db4&lt;/strong&gt; database has the following tables:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;_Attributes: &lt;/strong&gt;this has the exact same structure as the _Attributes table in static.db4&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;_Globals:&lt;/strong&gt; this is a simple global variable storage managed by the &lt;strong&gt;GlobalAttrsManager&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Instance tables: &lt;/strong&gt;the instance tables as listed in the _Categories table of static.db4. Every game entity in the entire game has a row in one of the instance tables. The general structure of an instance table is the same as the associated template table, but with the following additional columns:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;Guid (guid, primary, unique, indexed): &lt;/strong&gt;a unique identifier for the entity&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;_ID (string): &lt;/strong&gt;a human-readable unique identifier (only within the level)&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;_Level (string, indexed): &lt;/strong&gt;the level where this entity currently resides (may change during game)&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;_Layers (string):&lt;/strong&gt; The layers this entity is a member of. Entity layers can be used to “overlay” a specific group of entities at level load time. This can be used for day/night, intact/destroyed versions of a level without duplicating the entire level. An empty _Layers attribute means that this entity is always loaded into a level.&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;Transform (matrix44):&lt;/strong&gt; the current world space transform of the entity&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;p&gt;The &lt;strong&gt;_Instance_Levels&lt;/strong&gt; instance table is special in that it doesn’t have the above mentioned hardcoded attributes. Instead it contains one row per level in the game with the following attributes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Id (string, primary, unique, indexed):&lt;/strong&gt; a unique-id string of the level&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Name (string, indexed):&lt;/strong&gt; the human-readable name of the level&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;StartLevel (bool):&lt;/strong&gt; true if this is the start level which should be loaded on New Game, false for all other levels&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;_Layers (string):&lt;/strong&gt; the currently active entity layers&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Center (vector3):&lt;/strong&gt; the midpoint of the level in world space&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Extents (vector3):&lt;/strong&gt; the extents vector of the level (Center and Extents are used to describe the bounding box of the level)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;NavMesh, NavMeshTransform, NoGoArea, NoGoAreaTransform: &lt;/strong&gt;used by the navigation subsystem (not currently implemented in Nebula3)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Most entity-related database accesses are wrapped by the CategoryManager, which currently caches most of the data in memory (all template tables, and all entity instance data of the current level). This may change in the future when we generally run SQLite through the in-memory mode. If the in-memory database accesses are fast enough we might drop the caching (which isn’t as good as I’d like because of the huge amount of memory allocations going on during reading from the database).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3201187180847297586?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3201187180847297586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3201187180847297586' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3201187180847297586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3201187180847297586'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/02/n3s-game-database-structure.html' title='N3’s Game Database Structure'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3146608274820291548</id><published>2009-02-07T16:06:00.002+01:00</published><updated>2009-02-21T15:19:51.222+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>EVA</title><content type='html'>&lt;p&gt;I think I have a pretty good plan now for Nebula3’s asynchronous job subsystem, and (most importantly) I have a nifty name for it: EVA (Eingabe-Verarbeitung-Ausgabe, engl.: Input-Processing-Output). A job object is basically a piece of input data plus some code which asynchronously processes that data, resulting in the output data. Hence EVA. The main motivation is of course to make use of the PS3 stream processing units (I know, I know, the S in SPU actually stands for synergistic, but I think that’s wishful thinking at least in the context of a game engine, processing of individual data streams makes more sense then chaining the SPUs together IMHO, but I digress…). &lt;/p&gt;  &lt;p&gt;I really don’t want an entire, important subsystem in N3 which only makes sense on the PS3 though. EVA jobs should also work on the CPU or GPU if desired.&lt;/p&gt;  &lt;p&gt;The 2 main inspirations are Insomniacs “&lt;a href="http://www.insomniacgames.com/tech/articles/0907/files/spu_shaders_introduction.pdf" target="_blank"&gt;SPU Shaders&lt;/a&gt;” (treat a SPU job like a GPU shader), and DX11’s Compute Shaders (use GPU shaders for non-rendering purposes). &lt;/p&gt;  &lt;p&gt;The main problem is to provide a simple, generic interface of how to get data to and from “external computation units” with as little synchronization as possible. GL and D3D had to solve that problem years ago in order to let the GPU work in parallel to the CPU. Vertex buffers and textures provide the input data, which is processed by shader code and the output is written to render targets. It’s a simple and intuitive pattern of how to communicate with an asynchronous processing unit, and best of all, every programmers knows (or should know) those concepts in and out.&lt;/p&gt;  &lt;p&gt;EVA will simply wrap existing ideas under a common subsystem, with the emphasis on data-compatibility, not code compatibility. It should be relatively easy to “port” a job between the CPU, GPU or SPU. The main problem (how to structure the input and output data) should only be solved once (with the general rule-of-thumb that related data should be placed near to each other), while the processing code needs to re-written for each processing unit type (FX/HLSL for GPU jobs, simple, self-contained C or C++ code for CPU and SPU jobs).&lt;/p&gt;  &lt;p&gt;Thus an EVA job object would have the following properties:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;one or more input buffers &lt;/li&gt;    &lt;li&gt;one output buffer &lt;/li&gt;    &lt;li&gt;a small set of input parameters &lt;/li&gt;    &lt;li&gt;the actual processing code &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Buffers usually contain a stream of uniform data elements (similar to vertices or pixels), the input parameters can be used to cheaply tweak the behavior of an existing job object.&lt;/p&gt;  &lt;p&gt;For a CPUJob, the input and output buffers would be simple system memory buffers, and the processing code would be standard C/C++ code which is running in a thread of a thread-pool. The processing code should not call any “non-trivial” external functions as to remain somewhat portable to the other job types.&lt;/p&gt;  &lt;p&gt;A “DX9PixelShaderJob” would use textures as input buffers, and a render target as output buffer, the input parameters and the processing code would be described by an FX shader file.&lt;/p&gt;  &lt;p&gt;SPU jobs would need a way to manually pull data from the input buffers to local memory, and to write blocks of processed data back to the output buffer, possibly using some sort of double buffering.&lt;/p&gt;  &lt;p&gt;A way to cheaply convert/map buffers between the different job types would be desirable (for instance to use an output buffers directly as a DX texture, etc…). DX10 provides a pattern for this with its “resource views”.&lt;/p&gt;  &lt;p&gt;A great plan is the simple part of course, the devil is in the implementation. And once EVA is ready for action the true challenge will be to “de-fragment” the game-loop in order to identify and isolate jobs which can be handled asynchronously.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3146608274820291548?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3146608274820291548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3146608274820291548' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3146608274820291548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3146608274820291548'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/02/eva.html' title='EVA'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4744589826536208275</id><published>2009-02-01T14:24:00.002+01:00</published><updated>2009-02-21T15:20:08.102+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>Status Update</title><content type='html'>&lt;p&gt;In the 3 months before Christmas, we assembled a small tiger team of 4 programmers to port a prototype demo we created with the N2-based Drakensang engine on the PC over to the 360 running on top of N3. We had the demo up and running in 720p rendering resolution with 4xMSAA at 30+ fps right before Christmas, exactly as planned. The primary goal was to have something nice to show to publishers running on the 360, but we also wanted to bring our technology a few steps forward. We could have opted for doing a quick’n’dirty port: just use the existing N2-based source code, and make it run on the 360. This would have solved the primary task - have something to show on the 360 - but underneath the hood the demo would still run on an “old” PC engine, hacked to run on the 360. We wouldn’t have benefited on a technological level from this. Instead we decided to start a real “engineering project”, and re-build the demo from scratch on top of N3, only reusing the existing art assets.&lt;/p&gt;  &lt;p&gt;In hindsight, this was exactly the right decision. Nebula3 was developed with the 360 in mind from day one and the multithreaded rendering pipeline was already up and running on the 360. To my slight surprise we had very good performance right from the start. Due to the relatively complex pixel shaders and postprocessing effects in the PC demo I was expecting to see a framerate of somewhere between 15 and 25 frames, and then optimize from that point on. Instead we were very well north of 30 frames through the whole project with a 1280x720 render resolution and 4xMSAA. For a 3 year old graphics chip, this is remarkable. The prototype is very light on the game logic side so the main thread is basically idling on the frame synchronization point all the time. The rendering is fully limited by the GPU’s fill-rate, and we have a nice chunk of CPU time free on the render-thread side. We basically have a perfect graphical benchmark now to play around with and get a feeling for what the 360 can do, with most of the CPU still free for game logic, physics and dynamic rendering effects.&lt;/p&gt;  &lt;p&gt;There’s still a lot of opportunity to fine-tune the CPU/GPU interaction in the render thread, but with the rendering performance out of the way this early we could concentrate on adding missing features to N3, like the new animation, character rendering and particle subsystems. We had the luxury to do a complete and clean rewrite for those, and I’m quite happy how they turned out (well, except for some parts of the particle system where we had to be bug-compatible with N2 to make the rendering result look identical using the existing source parameters). We have SQLite running on the 360 using the in-memory-database feature now, which we will probably back-port to our PC projects as well since it’s generally a nice-to-have feature. zlib, TinyXML and Lua had already been brought over before.&lt;/p&gt;  &lt;p&gt;Finally, we now have a completely identical new PC-version of the prototype as a “side effect”. Our entire build-pipeline is now multiplatform-capable, a specific target platform is selected by a simple command line switch when running the MSBuild script. This is very nice even for a pure 360-project. Game logic code and even most of the engine code is platform-agnostic and can be implemented and tested on the PC, without the programmer hogging one of the ever-precious devkits. Switching to the 360-build for testing, debugging and optimization work is just a matter of seconds.&lt;/p&gt;  &lt;p&gt;The next (and I think - final) big thing for N3 is a proper asynchronous resource streaming system specifically optimized for console platforms. N3 already has the concept of loading resources asynchronously through the managed resource system, but that is only one fairly low-level building block. What’s missing is a resource streaming system which basically acts as a fixed-size memory cache between the graphics chip and the disc.&lt;/p&gt;  &lt;p&gt;The main disadvantage of consoles (compared to the PC) is the slow data rate and poor seek times of DVD and Bluray. But the good thing on consoles is, that the resource setup process has been opened up to the programmer. On the PC, DirectX and OpenGL are both very black-boxy when it comes to resource handling. The programmer never really knows what happens inside the API and graphics driver when a new texture is created or prepared for rendering. This black box is unlocked and documented on pretty much all consoles platforms, so that it makes very much sense to write platform specific resource streaming systems. &lt;/p&gt;  &lt;p&gt;All in all I’m now very confident that N3 can handle a real-world project on the PC and/or 360. We have a very good feeling for what the 360 can and can’t do, the 360 is now integrated into our build pipeline, and N3 itself is pretty much feature-complete from our point of view.&lt;/p&gt;  &lt;p&gt;I’d really love to put up a screenshot of our prototype since it looks pretty sweet on the 360. But it’s currently under cover and for publisher’s eyes only, so unfortunately I can’t.&lt;/p&gt;  &lt;p&gt;I’ll try to get a new N3 SDK out soon (of course without the 360 stuff, as usual).&lt;/p&gt;  &lt;p&gt;Oh, and &lt;a href="http://marketplace.xbox.com/en-US/games/media/66acd000-77fe-1000-9115-d802584108c2/" target="_blank"&gt;The MAW&lt;/a&gt; is awesome. Definitely give it a try!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4744589826536208275?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4744589826536208275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4744589826536208275' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4744589826536208275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4744589826536208275'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/02/status-update.html' title='Status Update'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5890770329052548373</id><published>2009-01-27T20:53:00.001+01:00</published><updated>2009-01-27T20:53:27.311+01:00</updated><title type='text'>Iron Curtain</title><content type='html'>&lt;p&gt;Rant: Microsoft needs to sort out this fucking mess with region-locking on Xbox Live. See: as a German Xbox360 owner it’s like back in the Cold War, but this time it’s not just the Eastern Germans who are fucked because they were born on the wrong side of the Iron Curtain. We’re condemned to buy overpriced, censored, poorly localized games. If they’re available at all. &lt;/p&gt;  &lt;p&gt;Which itself is not a problem for every 360 owner in his right mind. Simply order the UK version of a game, which is usually cheaper, has the original voice tracks, and isn’t mutilated beyond recognition. That’s all good and dandy until it comes to DLC. In the good old days before The Wall was erected (this was around the time when the movie download service started on XBL), this was not a problem either. Just create an English Live account, upload a few space bucks, and buy the matching DLC for the UK version of a game. Not so anymore! A strict IP address check is performed now. If you’re dialing in through a German provider you’re fucked. There is a way to circumvent this by using a foreign VPN service. But come on! We’re living in the free world now, not in some frigging soviet colony.&lt;/p&gt;  &lt;p&gt;The whole situation is really a completely incomprehensible mess:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;some games are not released in Germany at all, mostly Microsoft first-party games, for instance Gears Of War 1 and 2, Ninja Gaiden 2 and Crackdown&lt;/li&gt;    &lt;li&gt;some games are released, but in a cut version (no blood, etc…)&lt;/li&gt;    &lt;li&gt;some games are released which are not cut at all (Dead Space, Resident Evil 5)&lt;/li&gt;    &lt;li&gt;some games have the original English voice track, some only have a localized track&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Somebody please explain to me, why a game like Resident Evil 5 is released here, while Crackdown (a comic game for fucks sake!) is not. Why does EA or Capcom manage to get USK-18 ratings for their *uncut* games with realistically exploding heads and all, while Microsoft doesn’t even bother? And why the fuck does Microsoft care at all if the USK doesn’t want to rate a game? Put a fucking “this game is unrated” sticker on the box and be done with it like everybody else does. It’s not like its forbidden to sell a game in Germany which didn’t get a rating.&lt;/p&gt;  &lt;p&gt;And instead of working their ass off to fix this Kafkaesque situation, the German Xbox product manager writes this on his blog: &lt;a title="http://www.dreisechzig.net/wp/archives/1572" href="http://www.dreisechzig.net/wp/archives/1572"&gt;http://www.dreisechzig.net/wp/archives/1572&lt;/a&gt; (short translation: don’t buy English).&lt;/p&gt;  &lt;p&gt;The solution has to be: let me access downloadable content for games I legally own. Period. &lt;/p&gt;  &lt;p&gt;Rant off.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5890770329052548373?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5890770329052548373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5890770329052548373' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5890770329052548373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5890770329052548373'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/01/iron-curtain.html' title='Iron Curtain'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4355141317970820326</id><published>2009-01-25T15:57:00.001+01:00</published><updated>2009-01-25T15:57:53.800+01:00</updated><title type='text'>МГС3 Сабсистенс</title><content type='html'>&lt;p&gt;I’m currently playing Metal Gear Solid 3 Subsistence on the PS2 (the new chase camera is wonderful), and also started a new MGS4 run in parallel. I just wanted to make sure that I’m not a victim of nostalgia with my opinion that MGS3 is the better game. To make a long story short: MGS4 lost again. This time I played MGS4 “old-school”, no rifles, just the knife and the tranquilizer pistol. This makes the game much more fun, but still I couldn’t get past chapter 2 before getting bored.&lt;/p&gt;  &lt;p&gt;With MGS3 however I felt the same urge to continue playing like the first time. The story and cut-scenes are great and never boring, Volgin is a wonderful villain straight out of an old Bond movie, the boss-fights are truly unique (the legendary sniper duel with The End!), and the whole stealth and survival game-play is much more fleshed out compared to its successor… Looking at all this goodness I wonder how the hell MGS4 could happen. There were so many great elements in the previous MGS games which have been dumped and replaced with all this “shooter-crap” which doesn’t fit at all into an MGS game… And the only thing I can remember from the MGS4 story is that nanomachines are bad (damn nanomachines, first they ruin Star Wars, and now look what they done to MGS!).&lt;/p&gt;  &lt;p&gt;An MGS3 re-release on PSN (or XBLA hehe) in anti-aliased 720p and maybe a high-res texture pack would make me a happy gamer. The actual 3d models still look surprisingly good (the tree models and the grass for instance are better then in many current-gen games).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4355141317970820326?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4355141317970820326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4355141317970820326' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4355141317970820326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4355141317970820326'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/01/3.html' title='МГС3 Сабсистенс'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-162988875353586203</id><published>2009-01-17T19:43:00.001+01:00</published><updated>2009-01-17T21:47:54.195+01:00</updated><title type='text'>Notebook</title><content type='html'>&lt;p&gt;The keyboard of my Vaio is starting to act funny, and I guess the 512MB RAM and 50GB hard disc don’t quite cut it anymore either. It’s been serving me well for the past 3 years, longer then any desktop PC I had before, so I think it’s time to finally put it to rest. I’m currently ogling the &lt;a href="http://www.guardian.co.uk/technology/blog/2008/sep/01/samsungx360billedaslighter" target="_blank"&gt;Samsung X360&lt;/a&gt;, the only things I don’t like is the price and the Intel graphics chip. But damn everything else is sexy. I have the following must-haves for my notebook of choice:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;a 13.5 inch display, this makes the notebook just as big as an A4 sheet of paper, anything smaller is too small, and anything bigger is too clunky :) &lt;/li&gt;    &lt;li&gt;weight, I’m dragging around the notebook quite a bit, so the lighter, the better &lt;/li&gt;    &lt;li&gt;battery life, I like to work when travelling by train, but only ICE trains have power sockets in Germany &lt;/li&gt;    &lt;li&gt;needs to run VisualStudio, and must be able to run my own DirectX stuff (this rules out MacOS X, and using a Powerbook to run Windows is kind of a sacrilege, oh and… only web designers use Macs, rite?) &lt;/li&gt;    &lt;li&gt;needs to have at least Shader Model 3.0 graphics &lt;/li&gt;    &lt;li&gt;needs to have enough oompfh for Vista and Windows 7 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Some of the new Vaios are runner-ups as well, but they are even more overpriced then the X360 (which is quite typical for Sony products) and I loath how Sony pre-loads the machine with heaps of useless software. I need to check out whether Samsung is guilty of this as well, but it’s hard to imagine they’d be worse then Sony.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-162988875353586203?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/162988875353586203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=162988875353586203' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/162988875353586203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/162988875353586203'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/01/notebook.html' title='Notebook'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6286617332641987529</id><published>2009-01-17T19:01:00.001+01:00</published><updated>2009-01-17T19:06:45.702+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>Animation</title><content type='html'>&lt;p&gt;As I wrote in my &lt;a href="http://flohofwoe.blogspot.com/2008/11/coreanimation.html" target="_blank"&gt;CoreAnimation&lt;/a&gt; post, the Nebula2 animation system was in dire need of a new design and a clean rewrite. During &lt;a href="http://www.radonlabs.de/gamesdrakensang.html" target="_blank"&gt;Drakensang’s&lt;/a&gt; development and another research project which focused on facial animation, we had to add new features on a system which wasn’t designed for those capabilities. The resulting system worked, but just barely, and from a design standpoint it became quite an un-maintainable mess. When working within the constraints of a commercial project (defined by milestone dates, features and quality), this is often the only choice, it’s usually better to have something working at the end of the day (even though it’s a bit ugly internally), then to slip milestones. At least it was clear, what features would be important for a clean redesign, and how they &lt;strong&gt;shouldn’t&lt;/strong&gt; be implemented.&lt;/p&gt;  &lt;p&gt;With Nebula3 as an experimentation test-bed I started to work on a new animation system even before Drakensang was finished. Some of the main problems of the old system were:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;animation low-level and high-level features where implemented all over the place, some in Nebula2, some in Mangalore, some in the application&lt;/li&gt;    &lt;li&gt;sampling at random points in time wasn’t properly supported (the cross blending code required that the sampling time was modified at positive increments)&lt;/li&gt;    &lt;li&gt;there was no priority blending, and blend weights had been normalized to add up to 1, this gave “funny results” unless the application provided “carefully tuned” blend weights&lt;/li&gt;    &lt;li&gt;blending of partial animation (where only a part of a character skeleton is animated) wasn’t properly supported at first, and sort-of hacked in later&lt;/li&gt;    &lt;li&gt;it wasn’t possible to blend 2 identical animations at different sampling times&lt;/li&gt;    &lt;li&gt;animation clips could not be started in the future or past&lt;/li&gt;    &lt;li&gt;… and a lot of small bugs and quirks which resulted from the growing complexity of the animation system &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The first design choice was to split the animation code into 2 subsystems: CoreAnimation and Animation. CoreAnimation has already been described &lt;a href="http://flohofwoe.blogspot.com/2008/11/coreanimation.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;While CoreAnimation mainly cares about resource management, the higher-level Animation system provides features to implement complex animation blending scenarios.&lt;/p&gt;  &lt;p&gt;When starting the Animation subsystem I was considering blend trees. The leaves of a blend tree would be sampling nodes, which sample a single animation clip at a specific time, and the nodes of the tree would accept sampled data at the input connectors, mix (or otherwise process) the incoming data into a single output connector, until, at the root node of the tree, the final result would be available. After a few weeks of work and several interface revisions it became clear that working with such a system would be much more complicated then even with the old Nebula2 animation system. When feeding the blend tree system with “real world scenarios” I never ended up with a satisfactory simplicity, instead even relatively simple blending scenarios looked incredibly complex.&lt;/p&gt;  &lt;p&gt;Thus I scrapped blend trees, and started anew with a more straight-forward priority-blending system based on animation tracks (roughly like Maya’s Trax Editor works). With this new approach, everything suddenly fell into place, and after just a few days, a first implementation was finished.&lt;/p&gt;  &lt;p&gt;The new Animation system has 2 important object types: &lt;strong&gt;AnimJob&lt;/strong&gt; and &lt;strong&gt;AnimSequencer&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;An AnimJob represents a single animation with the following attributes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Start Time:&lt;/strong&gt; The start time of an AnimJob, can be in the past or in the future.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Duration: &lt;/strong&gt;The duration of the AnimJob, doesn’t have to correlate with an animation clip’s length, it can also be infinite.&lt;strong&gt;&amp;#160;&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Blend Priority: &lt;/strong&gt;The AnimSequencer class implements priority-blending, where higher priority clips dominate lower priority clips. Thus a high priority clip with a blend weight of 1.0 will completely obscure any previous lower priority clips.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Blend Weight: &lt;/strong&gt;The final weight used for priority blending inbetween the fade-in and fade-out period. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Fade-In / Fade-Out Time: &lt;/strong&gt;the time used to smoothly blend the clip with the current previous result.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;With the Start Time, Duration and Blend Priority attributes, AnimJobs can be arranged by an AnimSequencer object in a 2D coordinate system where the horizontal axis is time, and the vertical axis is blend priority. When sampling at a given point in time, the AnimSequencer first finds all animation jobs which cross the sampling position. Then, starting with the lowest priority animation job, each active job is evaluated and the resulting animation samples are priority-blended with the previous blending result.&lt;/p&gt;  &lt;p&gt;AnimJob is just a base class which can be subclassed to hook custom functionality into the blending process (like inverse kinematics, or some lookat-target functionality). At the moment there is only one specific subclass: &lt;strong&gt;PlayClipJob&lt;/strong&gt;, which simply samples an animation clip.&lt;/p&gt;  &lt;p&gt;The new Animation subsystem fixes pretty much all problems of the old Nebula2 system:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;automatic blend-weight normalization has been replaced with priority-blending which is much more useful in typical blending scenarios&lt;/li&gt;    &lt;li&gt;it’s now possible to correctly evaluate animations at random points in time, with correct cross-fading&lt;/li&gt;    &lt;li&gt;correct blending of partial animations (where an animation only manipulates parts of a character skeleton) is now a standard feature&lt;/li&gt;    &lt;li&gt;animation clips can now be blended with themselves&lt;/li&gt;    &lt;li&gt;animation jobs can be started in the future or in the past&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Overall, the new Animation system is much simpler, robust, easier to use and easier to understand.&lt;/p&gt;  &lt;p&gt;A few things are still missing which proved useful in the past, or which we identified as a nice-to-have-feature:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Some sort of name-mapping for animation clips:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;In Drakensang, every character had about 400..600 animations, most of those were combat animation variations (different attack types, different weapons, with or without shield, etc…), but the animations actually fell into only a few categories (like attack, idle, walk, …).&lt;/li&gt;      &lt;li&gt;It would be nice if a mapping mechanism would exist, where the application sets a few variables (like type of weapon in hand, shield in hand, etc…), and then maps an abstract animation name like “attack” to a specific name like “male_twohandedsword_attack1” by resolving a few user-defined mapping rules.&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Some sort of finite-state-machine to define how animations relate to each other.&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;This is mainly useful to automatically play transition animations. For instance, if a character currently has no weapon equipped, but he needs to play an attack animation, the state machine would decide that a “draw sword” animation needs to be played first.&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6286617332641987529?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6286617332641987529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6286617332641987529' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6286617332641987529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6286617332641987529'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/01/animation.html' title='Animation'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2278447949437478430</id><published>2009-01-05T19:01:00.001+01:00</published><updated>2009-01-05T19:01:49.071+01:00</updated><title type='text'>Vista</title><content type='html'>&lt;p&gt;Today I'm finally doing the transition to Vista. After my first and failed attempt in &lt;a href="http://flohofwoe.blogspot.com/2007/04/back-to-xp.html"&gt;April 2007&lt;/a&gt; I've now got a new work desktop with 32-bit Vista installed: a Dell XPS with Core2 Duo, 4 GB RAM, NVIDIA 9800 GT and a 700 GB hard disc. It's huge and f*ck-ugly (a true PC indeed), and it glows blue in the dark. Seriously, who's designing those machines nowadays, and for what target audience?&lt;/p&gt;  &lt;p&gt;I'm pretty happy with Vista now. Looks like all the problems from 2 years ago have been fixed, disc and network performance seems good, and everything feels &amp;quot;snappier&amp;quot; then on my previous machine (although, given the better hardware specs, it better should!)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2278447949437478430?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2278447949437478430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2278447949437478430' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2278447949437478430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2278447949437478430'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/01/vista.html' title='Vista'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7515618929826171343</id><published>2009-01-05T18:33:00.001+01:00</published><updated>2009-01-05T18:40:38.729+01:00</updated><title type='text'>Testing Windows Live Writer...</title><content type='html'>&lt;p&gt;Looks like I found a new editor for my blog posts: Windows Live Writer. It's part of the messenger download package here: &lt;a title="http://get.live.com/" href="http://get.live.com/"&gt;http://get.live.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Will checkout the email tool on my private notebook soon. Everything seems to work together with Google services. I think Microsoft finally starts to understand how that Internet thing works ;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7515618929826171343?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7515618929826171343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7515618929826171343' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7515618929826171343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7515618929826171343'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2009/01/testing-windows-live-writer.html' title='Testing Windows Live Writer...'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6975499864225760093</id><published>2008-12-30T15:12:00.002+01:00</published><updated>2008-12-30T16:40:44.859+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Games Of The Year</title><content type='html'>My personal GOTY's for 2008:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Fallout 3: &lt;/span&gt;I was very skeptical at first, but after 1.5 playthroughs (and counting) I must say that this is the best Bethesda game yet. In my opinion, the Fallout world fits the "Bethesda school of game design" much better then the phantasy world of the Elder Scrolls. And gameplay-wise, Fallout is quite a bit more streamlined then Oblivion, keeping the player engaged without giving up too much freedom.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Ninja Gaiden 2:&lt;/span&gt; Yeah, the game was rushed and there are some obvious flaws, but the combat in NG2 is simply spectacular. I must have played through the game eight or nine times, and I'm currently in the middle of my first Mentor run. I wish there would be hope for some sort of refined "NG2 Black", but with Itagaki's leave from Tecmo chances seem to be void :(&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Dead Space:&lt;/span&gt; This game came out of nowhere for me, and in fact, it's hard to describe, why the game is so great. Dead Space is basically "Doom3, done right", and that's all there needs to be said. It's an old-school corridor shooter with shiny graphics and rock-solid shooting mechanics. And I can't get over the fact that this is an EA game. EA!!!&lt;/li&gt;&lt;/ul&gt;Live Arcade GOTYs: &lt;span style="font-weight: bold;"&gt;Castle Crashers&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;RezHD&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;BC: Rearmed&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;Omega Five&lt;/span&gt; (hmm, more great games on XBLA then retail this year...).&lt;br /&gt;&lt;br /&gt;Here's my XBLA wishlist for 2009: downloadable full games, and more price variety for downloadable games (in my opinion, a game like Mirror's Edge would be better if it wouldn't have to fill the shoes of a full-blown 60.- Euro game).&lt;br /&gt;&lt;br /&gt;See ya'all in 2009 :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6975499864225760093?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6975499864225760093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6975499864225760093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6975499864225760093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6975499864225760093'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/12/games-of-year.html' title='Games Of The Year'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9131299894590802052</id><published>2008-12-12T20:47:00.007+01:00</published><updated>2008-12-12T21:09:38.136+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Home (PSN)</title><content type='html'>I was just checking out Home, and to put it mildly, I was not impressed:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I was trying for about 15 minutes to get past the start screen, getting all types of connection errors, then suddenly... one connection attempt worked, as a "casual user" I would have given up after the first four or five errors (which do have intuitive names like "C931").&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I tried for 10 minutes to create a character which doesn't look like shit and failed.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Downloads and long loading times between sections totally kills the "experience".&lt;/li&gt;&lt;li&gt;Everything basically looks and feels like it has been designed by yuppie marketeers stuck in the 90's.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I doubt I will ever return. Even if Home was "the cool shit", the long startup time kills every impulse to even launch that thing.&lt;br /&gt;&lt;br /&gt;I don't know... I refuse to believe that Sony is driven by marketing peeps who thought that Second-Life is the next-big-thing during its short media-hype. I just don't "get" it. But who knows, I wasn't "getting" the Wii either, and look how that turned out (yeah, who am I kidding, it's more likely that Home will turn into a wasteland and Sony will let it die a quiet and slow death in a few months). Hmm... wasteland... time to return to Fallout3 :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9131299894590802052?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9131299894590802052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9131299894590802052' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9131299894590802052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9131299894590802052'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/12/home-psn.html' title='Home (PSN)'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5837679221781361871</id><published>2008-11-22T13:58:00.008+01:00</published><updated>2008-11-22T15:04:06.200+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Month of Shooters</title><content type='html'>I'm currently playing through the Gears 2 single player campaign, and I don't know why exactly, but I'm not having very much fun. There are a few easy to identify points which I clearly don't like:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Vehicle sequences: I don't know why FPS designers still torture us with vehicle sequences. The mini-tank in Gears 2 controls like shit (a bit like the Mass Effect Mako, but worse), and there's too much driving through boring tunnels with nothing else happening.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Stupid story: So far I'm not seeing the better story that was promised. Instead I'm just seeing Dom bringing up his wife all the time (just found her yesterday). What is this emotional bullshit doing in my Gears... really. If you want to do an emotional story, do it right. The Gears main character are simply not built for stuff like this. It's like asking Schwarzenegger to play Shakespeare. Some things simply don't work, no matter how hard one tries.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Dialog: alright, Marcus isn't exactly a second Cicero when it comes to conversational skills, but those stupid one-liners get old pretty fast.&lt;/li&gt;&lt;li&gt;Too much brown: I know it's cliche, but Gears could just as well be played on an old black-and-white monitor and not a lot of information would be lost. I'm sick of monochromatic shooters.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Except from the vehicle sequences (which are inexcusable) I can live with the other points. I like my bad story and cheesy dialogs, if there's a good game at the core.&lt;br /&gt;&lt;br /&gt;But somehow, the core gameplay isn't very satisfying to me in Gears2. I've been playing into the COD4 single-player-campaign again for comparison, and holy shit this an entirely different level, even the "quiet moments" in COD4 are packed with action.&lt;br /&gt;&lt;br /&gt;Gears2 brings up unbelievable stuff like mile-long worms, giant fish and whole cities sinking into the ground, but it doesn't grab me. Maybe it is because the scale is too big, or maybe it is because the actual fire fights aren't very exciting. I think maybe the main reason why the game leaves me cold is that there are too long pauses between fire fights, and fights are too predictable. Coming into an area with a lot of conveniently placed barricades? Sure as hell a few seconds later a door will shut behind you and Locust will start attacking.&lt;br /&gt;&lt;br /&gt;Good thing Dead Space came along, otherwise I might have lost my faith in shooters ;)&lt;br /&gt;&lt;br /&gt;I'm very impressed with the new Xbox dashboard, especially with the fast and painless update process (took maybe 2 minutes through my 16Mbit DSL line at home). I was prepared for the worst (something like 2 weeks without Xbox Live like last Christmas), but apart from a few glitches on the Marketplace which were fixed the next day everything went perfect. I love how responsive, fast and colorful everything is now, and the hard drive installation is a god-send because it turns off the jet-engine noise from the DVD drive.&lt;br /&gt;&lt;br /&gt;I even like the Avatar stuff more then I should. I've been trying to create a Ron Jeremy avatar, but that's where the avatar creator really comes to its limits. Here's my wishlist for the next update:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the current fat setting needs to be a lot fatter, the current maximum isn't even enough to build a realistic Elvis in his later years&lt;/li&gt;&lt;li&gt;more 70's porn star accessories and clothing please&lt;/li&gt;&lt;li&gt;more real hair styles(!), there's plenty of 90's neo-hippie shit, but no hair which nearly does Ron Jeremy justice&lt;/li&gt;&lt;li&gt;hair styles should include chest and armpit options&lt;/li&gt;&lt;/ul&gt;Since I did&lt;a style="" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_cWdorEDEaNg/SSgPL269xSI/AAAAAAAAAFI/M9pyqbMaqAM/s1600-h/flohofwoe.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 150px; height: 276px;" src="http://3.bp.blogspot.com/_cWdorEDEaNg/SSgPL269xSI/AAAAAAAAAFI/M9pyqbMaqAM/s400/flohofwoe.png" alt="" id="BLOGGER_PHOTO_ID_5271480060232975650" border="0" /&gt;&lt;/a&gt;n't find the right hair and clothes, I went for a Ron Jeremy/Princess Leia hybrid:&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5837679221781361871?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5837679221781361871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5837679221781361871' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5837679221781361871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5837679221781361871'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/11/month-of-shooters.html' title='Month of Shooters'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_cWdorEDEaNg/SSgPL269xSI/AAAAAAAAAFI/M9pyqbMaqAM/s72-c/flohofwoe.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4540514233270054121</id><published>2008-11-08T17:26:00.005+01:00</published><updated>2008-11-08T17:32:30.235+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>CoreGamer</title><content type='html'>It feels like this is the most packed holiday season of all time. It is a shame that publishers don't spread their releases a bit more over the year. There was hardly a single good game coming out every quarter for the 360, and now suddenly since end of October it feels like there's a block buster released every day. Unfortunately, a lot of great games will be buried under the heavy weights like Gears or Fallout3, but well who am I to complain. It's a great time for hardcore gamers across all platforms, and that's all that counts :)&lt;br /&gt;&lt;br /&gt;I think I'll have to work on the oncoming backlog until at least February next year, and careful scheduling is necessary to manage the avalanche of games indeed. Fortunately some of the games didn't turn out quite as good as pre-release-hype made me belief, so I can push a few games into next year. One of those is FarCry2. It's not a bad game by any means, I was prepared for the open-world-ness (which is the exact opposite of the original FarCry) and shitty to non-existent story (which is exactly in line with the original FarCry). But still I was disappointed. I must confess that I didn't give the game a real chance (only played for one evening, about 2 to 3 hours). Graphics are great, but game-play wise it is somewhere between Just Cause and Mercenaries2, and I already had my share of sandbox games this year I guess. However I will definitely come back to FC2 next year when the storm has settled a bit, but it looks like this will be the Assassin's Creed of 2008 (spectacular presentation, shallow gameplay).&lt;br /&gt;&lt;br /&gt;Next up was Fable2. Great game (especially with the downloadable English audio track), but I just haven't the time to appreciate the game as a whole. The game requires a lot of time investment, but rewards the player for the time spent with a great sense of immersion. But at the moment I just don't have the attention span required for a game like this. One thing I found surprising was, that one of my old favorites, Overlord, in places looks better or at least very similar to Fable2 (not a surprise, since the Overlord designers definitely drew a lot of inspiration from the original Fable), but considering that Overlord is a 2007 title, Fable2 should have been a prettier game. I was about half way through Fable2, when along came my personal surprise hit of 2008 (so far at least):&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dead Space!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;What a f*cking great game. It's a bit of Alien (the movie), a bit of System Shock, and a bit of Quake2, merged into a wonderfully old-school survival-horror-corridor-shooter. The really surprising bit is: this is an EA game! With the exception of Fight Night 3 and Skate, I wasn't interested in a single EA game for the entire life-time of the 360, and now all of the sudden, EA actually starts to produce great games in a row. This year alone I bought Battlefield BC, Mercenaries2 and Dead Space from EA, and will probably get Mirrors Edge soon. And considering that Bioware is now EA as well... oh dear. What has the world come to, EA making great games... The end must be near indeed hehe.&lt;br /&gt;&lt;br /&gt;The PS2 is now at 77 Euro in Germany, just a tad more expensive then a typical 360 or PS3 game. That's the latest model: slim, with integrated power supply, one dualshock, composite cables, looking sexy as hell (no memory card though). Since my last PS2 went MIA, this was a very good reason to impulse-buy a new one. Better investment then my PS3 to be honest. Just playing a few minutes into MGS3 again was worth it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4540514233270054121?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4540514233270054121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4540514233270054121' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4540514233270054121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4540514233270054121'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/11/coregamer.html' title='CoreGamer'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3694339185543527517</id><published>2008-11-08T16:12:00.003+01:00</published><updated>2008-11-08T16:13:45.383+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>CoreAnimation</title><content type='html'>Rewriting the animation system of Nebula2 was one of the big items on my personal to-do list for the last couple of months. Too many small features had been stacked on top of each other over time by too many programmers without that the underlying old code really supported the new stuff. The result was that the N2 animation system became a fragile and difficult to work with mess. It mostly does what it needs to do for Drakensang (which isn't trivial with its finely tuned animation queueing during comat), but it isn't elegant any more, and it is not really a joy to work with.&lt;br /&gt;&lt;br /&gt;I have only been working very sporadically on the new N3 animation code during the past few months, restarting from scratch several times when I felt I was heading into a wrong direction. In the past couple of weeks I could finally work nearly full-time on the new animation and character subsystems, and not too early, because only then I really was satisfied with the overall design. The new animation system should fix all the little problems we encountered during the development of Drakensang and offer a few new features which we wished we had earlier. And it resides under a much cleaner and more intuitive interface then before (this was the main reason why I started over several times, finding class interfaces which encapsulate the new functionality, but are still simple to work with).&lt;br /&gt;&lt;br /&gt;One of the earliest design decisions was to split the animation code into two separate subsystems. &lt;b&gt;CoreAnimation&lt;/b&gt; is the low level system which offers high-performance, simple building blocks for a more complex higher level animation system. The high-level &lt;b&gt;Animation&lt;/b&gt; subsystem sits on top of CoreAnimation and provides services like mapping abstract animation names to actual clip names, and an animation sequencer which allows easy control over complex animation blending scenarios.&lt;br /&gt;&lt;br /&gt;The main focus of CoreAnimation is high performance for basic operations like sampling and mixing of animation data. CoreAnimation may contain platform-specific optimizations (although none of this has been implemented so far, everything in CoreAnimation currently works with the Nebula3 math library classes). CoreAnimation also assumes that motion-capturing is the primary source of animation data. Like sampled audio vs. MIDI, motion capture data consists of a large amount of animation keys placed at even intervals instead of a few manually placed keys at random positions in the time-line. The advantage is that working with that kind of animation data can be reduced to a few very simple stream operations, which are well suited for SSE, GPUs or Cell SPUs. The disadvantage to a spline-based animation system is of course: a lot more data.&lt;br /&gt;&lt;br /&gt;Spline animation will be used in other parts of Nebula3, but support for this will likely go into a few simple Math lib classes, and not into its own subsystem.&lt;br /&gt;&lt;br /&gt;Although not limited to, CoreAnimation assumes that skinned characters are the primary animation targets. This does not in any way limit the use of CoreAnimation for animating other types of target objects, but the overall design and optimizations "favours" the structure and size of animation data of a typical character (i.e. hundreds of clips, hundreds of animation curves per clip, and a few hundred to a few thousand animation keys per clip).&lt;br /&gt;&lt;br /&gt;Another design limitation was, that the new animation system needs to work with existing data. The animation export code in the Maya plugin, and the further optimization and bundling during batch processing isn't exactly trivial, and although much of the code on the tools side would benefit from a cleanup as well (as is usually the case for most of the tools code in a production environment), I didn't feel like rewriting this stuff as well, especially since there's much more work in the tools-side of the animation system compared to the runtime-side.&lt;br /&gt;&lt;br /&gt;So without further ado I present: the classes of CoreAnimation :)&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;AnimResource: &lt;/b&gt;The AnimResource class holds all the animation data which belongs to one target object (for instance, all the animation data for a character), that is, an array of AnimClip objects, and an AnimKeyBuffer. AnimResources are normal Nebula3 resource objects, and thus can be shared by ResourceId and can be loaded asynchronously.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;StreamAnimationLoader&lt;/b&gt;: The StreamAnimationLoader is a standard stream loader subclass which initializes an AnimResource object from a data stream containing the animation data. Currently, only Nebula2 binary .nax files are accepted.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;AnimKeyBuffer: &lt;/b&gt;This is where all the animation keys live for a single AnimResource. This is just a single memory block of float4 keys, no information exists in the key buffer how the keys relate to animation clips and curves. However, the animation exporter tools make sure that keys are arranged in a cache-friendly manner (keys are interleaved in memory, so that the keys required for a single sampling operation are close to each other in memory).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;AnimClip:&lt;/b&gt; An AnimClip groups a set of AnimCurves under a common name (i.e. "walk", "run", "idle", etc...). Clip names are usually the lowest level component a Nebula3 application needs to care about when working with the animation subsystem. Clips have a number of properties and restrictions:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;a human-readable name, this is stored and handed around as a StringAtom, so no copying of actual string data happens&lt;/li&gt;&lt;li&gt;a clip contains a number AnimCurves (for instance, a typical character animation clip has 3 curves per skeleton-joint, one for translation, rotation and scaling of each joint)&lt;/li&gt;&lt;li&gt;all anim curves in a clip must have the same key duration and number of keys&lt;/li&gt;&lt;li&gt;a clip has a duration (keyDuration * numKeys)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;a pre-infinity-type and post-infinity-type defines how a clip is sampled when the sample time is outside of the clip's time range (clamp or cycle).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;AnimCurve: &lt;/b&gt;An AnimCurve groups all the keys which describe the change of a 4D-value over a range of time. For instance, the animated translation of a single joint of a character skeleton in one clip is described by one animation curve in the clip. AnimCurves don't actually hold the animation keys, instead they just describe where the keys are located in the AnimKeyBuffer of the parent AnimResource. AnimCurves have the following properties:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Active/Inactive&lt;/b&gt;: an inactive AnimCurve is a curve which doesn't contribute to the final result, for instance, if an AnimClip only animates a part of a character skeleton (like the upper body), some curves in the clip are set to inactive. Inactive curves don't have any keys in the key buffer.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Static/Dynamic&lt;/b&gt;: an AnimCurve whose value doesn't change over time is marked as static by the exporter tool, and doesn't take up any space in the anim key buffer.&lt;/li&gt;&lt;li&gt;&lt;b&gt;CurveType&lt;/b&gt;: this is a hint for the higher level animation code what type of data is contained in the animation curve, for instance, if an AnimCurve describes a rotation, the keys must be interpreted as quaternions, and sampling and mixing must use spherical operations.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Animation keys:&lt;/b&gt; There isn't any "AnimKey" class in the CoreAnimation system, instead, the atomic key data type is float4, which may be interpreted as a point, vector, quaternion or color in the higher level parts of the animation system. There is no support for scalar keys, since most animated data in a 3d engine is vector data, and vector processing hardware likes its data in 128 bit chunks anyway.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;AnimEvent:&lt;/b&gt; Animation events are triggered when the "play cursor" passes over them. The same concept has been called "HotSpots" in Nebula2. AnimEvents haven't been implemented yet actually, but nethertheless they are essential for synchronizing all types of stuff with an animation (for instance, a walking animation should trigger events when a foot touches the ground, so that footstep sounds and dust particles can be created at the right time and position, and finally events are useful for synchronizing the start of a new animation with a currently playing animation (for instance, start the "turn left" animation clip when the current animation has the left foot on the ground, etc...).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;AnimSampler: &lt;/b&gt;The AnimSampler class only has one static method called Sample(). It samples the animation data from a single AnimClip at a specific sampling time into a target AnimSampleBuffer. This is one of the 2 "front-end-features" provided by the CoreAnimation system (sampling and mixing). The AnimSampler is used by the higher level Animation subsystem.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;AnimMixer: &lt;/b&gt;Like the AnimSampler class, the AnimMixer class only provides one simple static Method called Mix(). The method takes 2 AnimSampleBuffers and a lerp value (usually between 0 and 1) and mixes the samples from the 2 input buffers into the output buffer (k = k0 + l * (k1 - k0)). The AnimMixer is used for priority-blending of animation clips higher up in the Animation subsystem.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;AnimSampleBuffer:&lt;/b&gt; The AnimSampleBuffer holds the resulting samples of the AnimSampler::Sample() method, and is used as input and output for the AnimMixer::Mix() method. An important difference from the AnimKeyBuffer is that the AnimSampleBuffer also has a separate "SampleCounts" array. This array keeps track of the number of the sampling operations which have accumulated for every sample while sampling and mixing animation clips into a final result. This is necessary for mixing partial clips correctly (clips which only influence a part of a character skeleton). The AnimSampler::Sample() method will set the sample count to 1 for each key which was sampled from an active animation curve, and to 0 for each inactive sample curve (which means, the actual sample value is invalid). Later when mixing 2 sample buffers the AnimMixer::Mix() method will look at the input sample counts, and will only perform a mixing operation if both input samples are valid. If one input sample is invalid, no mixing will take place, instead the other (valid) sample will be written directly to the result. If both input samples are invalid, the output sample will be invalid as well. Finally, the AnimMixer::Mix() method will set the output sample counts to the sum of the input sample counts, thus propagating the previous sample counts to the next mixing operation. Thus, if at the end of a complex sampling and mixing operation the sample count of a specific sample is zero, this means that no single animation clip contributed to that sample (which probably should be considered a bug).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;That's it so far for the CoreAnimation subsystem, next up is the Animation subsystem which builds on top of CoreAnimation, and after that the new Character subsystem will be described, which in turn is built on top of the Animation system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3694339185543527517?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3694339185543527517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3694339185543527517' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3694339185543527517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3694339185543527517'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/11/coreanimation.html' title='CoreAnimation'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4256119323533878983</id><published>2008-10-01T12:03:00.002+01:00</published><updated>2008-10-01T12:07:13.200+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>Must Read</title><content type='html'>2 important and related blog posts:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://diaryofagraphicsprogrammer.blogspot.com/2008/09/shader-workflow-why-shader-generators.html"&gt;Shader Workflow - Why Shader Generators are Bad&lt;/a&gt;&lt;br /&gt;&lt;a href="http://realtimecollisiondetection.net/blog/?p=73"&gt;Graphical shader systems are bad&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Good arguments why shaders should be treated as code under programmer control, not as graphics assets under artist control.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4256119323533878983?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4256119323533878983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4256119323533878983' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4256119323533878983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4256119323533878983'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/10/must-read.html' title='Must Read'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6937267022299343933</id><published>2008-09-30T15:38:00.002+01:00</published><updated>2008-09-30T18:01:32.317+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>Line-counting</title><content type='html'>Some line-count trivia:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;table class="zeroBorder" id="ky36" width="100%" bgcolor="#ffd966" border="0" bordercolor="#000000" cellpadding="3" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="50%"&gt;Nebula3 Foundation Layer&lt;br /&gt;&lt;/td&gt;&lt;td width="50%"&gt;66,502 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width="50%"&gt;Nebula3 Render Layer&lt;br /&gt;&lt;/td&gt;&lt;td width="50%"&gt;73,465 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;Nebula3 Application Layer&lt;br /&gt;&lt;/td&gt;&lt;td valign="top"&gt;22,706 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;Nebula3 Addons&lt;br /&gt;&lt;/td&gt;&lt;td valign="top"&gt;32,847 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr bgcolor="#f6b26b"&gt;&lt;td valign="top"&gt;Nebula3 All&lt;br /&gt;&lt;/td&gt;&lt;td valign="top"&gt;195,520 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr bgcolor="#b6d7a8"&gt;&lt;td valign="top"&gt;Nebula2&lt;br /&gt;&lt;/td&gt;&lt;td valign="top"&gt;239,279 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr bgcolor="#b6d7a8"&gt;&lt;td valign="top"&gt;Mangalore&lt;br /&gt;&lt;/td&gt;&lt;td valign="top"&gt;181,592 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr bgcolor="#6aa84f"&gt;&lt;td valign="top"&gt;N2 + Mangalore&lt;br /&gt;&lt;/td&gt;&lt;td valign="top"&gt;420,871 lines&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The N3 line-count includes the current code for 3 platforms (Win32, Xbox360 and Wii), the N2+Mangalore count only includes one platform (Win32). Looks like N3 will end up a lot leaner then the old code which is a good thing :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6937267022299343933?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6937267022299343933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6937267022299343933' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6937267022299343933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6937267022299343933'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/09/line-counting.html' title='Line-counting'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7774039804971258390</id><published>2008-09-29T12:13:00.007+01:00</published><updated>2008-09-29T12:16:30.707+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>Nebula3 September SDK</title><content type='html'>Here's the new SDK:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.radonlabs.de/internal/N3SDK_Sep2008.exe"&gt;N3SDK_Sep2008.exe&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Please check my previous post for details, which got f*cked up pretty badly by importing it from Google Docs :(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7774039804971258390?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7774039804971258390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7774039804971258390' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7774039804971258390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7774039804971258390'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/09/nebula3-september-sdk.html' title='Nebula3 September SDK'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2321468467597118783</id><published>2008-09-27T15:05:00.002+01:00</published><updated>2008-09-27T15:07:53.013+01:00</updated><title type='text'>What's New in the September Nebula3 SDK</title><content type='html'>&lt;div style="HEIGHT:0px"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;I finally got around to pack a new N3 SDK together. I'll upload it on Monday when I'm back in the office, in the meantime here's a rough What's New list. A lot of under-the-hood-stuff has changed, and I had to remove a few of the fancy front-end-features for now (for instance, the N2 character rendering had to be removed when I implemented the multi-threaded renderer, and the shader lighting code is broken at the moment). I'll care about this front-end stuff in the next release.&lt;br /&gt;&lt;/div&gt;&lt;div style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;&lt;span class="Apple-style-span" style="font-size: 16px; "&gt;General Stuff&lt;/span&gt;&lt;br /&gt;&lt;/h3&gt;&lt;ul style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;&lt;br /&gt;  &lt;li style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;changes to enable mixing Nebula2 and Nebula3 code, mainly macro names are affected (DeclareClass -&gt; __DeclareClass, ImplementSingleton -&gt; __ImplementSingleton etc...)&lt;br /&gt;  &lt;/li&gt;&lt;li style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;started to remove #ifndef/#define/#endif include guards since pretty much all relevant compilers (VStudio, GCC, Codewarrior) support #pragma once &lt;br /&gt;  &lt;/li&gt;&lt;li style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;moved identical Win32 and Xbox360 source code into a common Win360 namespace to eliminate code redundancies&lt;/li&gt;&lt;li style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;added a new Toolkit Layer which contains helper classes and tools for asset export&lt;br /&gt;  &lt;/li&gt;&lt;li style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;added and fixed some Doxygen pages&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;h3&gt;Build System&lt;br /&gt;&lt;/h3&gt;&lt;ul style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;&lt;li&gt;re-organized VStudio solution structure, keeps all dependent projects in the same solution, so it's no longer necessary to have several VStudios open at the same time&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;it's possible now to import VStudio projects through the .epk build scripts (useful for actual Nebula3 projects which do not live under the Nebula3 SDK directory)&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;new "projectinfo.xml" file which defines project- and platform-specific attributes for the asset batch-export tools&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;split the export.zip archive into one platform-neutral and several platform-specific archives (export.zip contains all platform-independent files, export_win32.zip, export_xbox360.zip, export_wii.zip contain the platform-specific stuff)&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;added general multiplatform-support to the asset-pipeline (e.g. "msbuild /p:Platform=xbox360" to build Xbox360-assets)&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;new command-line build tools (with source):&lt;br /&gt;  &lt;/li&gt;&lt;ul style="MARGIN-TOP:0px; MARGIN-BOTTOM:0px"&gt;&lt;li&gt;audiobatcher3.exe (wraps audio export)&lt;/li&gt;&lt;li&gt;texturebatcher3.exe (wraps texture export)&lt;/li&gt;&lt;li&gt;shaderbatcher3.exe (wraps shader compilation)&lt;/li&gt;&lt;li&gt;buildresdict.exe (generates resource dictionary files)&lt;/li&gt;&lt;li&gt;these tools mostly just call other build tools (like xactbld3.exe, nvdxt.exe, or build tools for game-console SDKs)&lt;br /&gt;    &lt;/li&gt;&lt;/ul&gt;&lt;li&gt;note that the public N3-SDK only contains Win32 support for obvious legal reasons &lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;    Foundation Layer&lt;br /&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;fixed thread-safety bugs in Core::RefCounted and Util::Proxy refcounting code&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;added WeakPtr&amp;lt;&gt; class for better handling of cyclic references&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;added type-cast methods to Ptr&amp;lt;&gt;&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;simplified the System::ByteOrder class interface&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;added platform-specific task-oriented "virtual CPU core id's" (e.g. MainThreadCode, RenderThreadCore, etc...)&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;added a System::SystemInfo class&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;added Threading::ThreadId type and static Threading::Thread::GetMyThreadId() method&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;proper thread names are now visible in the VStudio debugger and other debugging tools&lt;/li&gt;&lt;li&gt;SetThreadIdealProcessor() is now used to assign threads to avaible CPU cores on the Win32 platform&lt;/li&gt;&lt;li&gt;new HTTP debug page for the Threading subsystem (currently only lists the active Nebula3 threads)&lt;/li&gt;&lt;li&gt;MiniDump support: crashes, n_assert() and n_error() now write MiniDump files on the Win32 platform&lt;/li&gt;&lt;li&gt;new Debug subsystem for code profiling:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;offers DebugTimer and DebugCounter objects&lt;/li&gt;&lt;li&gt;HTTP debug page allows to inspect DebugTimers and DebugCounters at runtime&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;new Memory::MemoryPool class for allocation of same-size memory blocks (speeds up allocation and reduces heap fragmentation)&lt;/li&gt;&lt;li&gt;some new and renamed methods in Math::matrix44&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;Http subsystem now runs in its own thread&lt;/li&gt;&lt;li&gt;added SVG support to Http subsystem (Http::SvgPageWriter and Http::SvgLineChartWriter)&lt;/li&gt;&lt;li&gt;added IO::ExcelXMLReader stream reader class, allows to read XML-formatted MS Excel spreadsheet files&lt;/li&gt;&lt;li&gt;added Behaviour mode to Messaging::AsyncPort, defining how the handler thread should wait for new messages:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;WaitForMessage: block until message arrives&lt;/li&gt;&lt;li&gt;WaitForMessageOrTimeOut: block until message arrives or time-out is reached&lt;/li&gt;&lt;li&gt;DoNotWait: do not wait for messages&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;added Remote subsystem, allows remote-controlling N3 applications through a TCP/IP connection&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" font-weight: bold; font-size:19px;"&gt;Render Layer&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;moved rendering into its own thread (InternalGraphics subsystem on the render-thread side, and Graphics front-end subsystem on the main-thread side)&lt;/li&gt;&lt;li&gt;added CoreAnimation and Animation subsystems (under construction)&lt;/li&gt;&lt;li&gt;added UI subsystem for simple user interfaces (under construction)&lt;/li&gt;&lt;li&gt;added CoreAudio and Audio subsystems (under construction):&lt;/li&gt;&lt;ul&gt;&lt;li&gt;CoreAudio is the back-end and runs in its own thread&lt;/li&gt;&lt;li&gt;Audio is the "client-side" front-end in the main-thread (or any other thread)&lt;/li&gt;&lt;li&gt;designed around XACT concepts&lt;/li&gt;&lt;li&gt;comes with XACT wrapper implementation&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;added CoreGraphics::TextRenderer and CoreGraphics::ShapeRenderer classes, both intended for rendering debug visualizations&lt;/li&gt;&lt;li&gt;added debug rendering subsystem (currently under the Debug namespace)&lt;/li&gt;&lt;li&gt;Frame subsystem: FramePostEffects may now contain FrameBatches&lt;/li&gt;&lt;li&gt;Input subsystem: disconnected XInput game-pad slots now only check every 0.5 seconds for connected game-pads&lt;/li&gt;&lt;li&gt;Resources subsystem: added ResourceAllocator/ResourceLump system to prepare for true resource streaming on console-platforms&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" font-weight: bold; font-size:19px;"&gt;Application Layer and Addons:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;removed CoreFeature (this stuff had to go into the GameApplication class to prevent some chicken-egg problems)&lt;/li&gt;&lt;li&gt;added NetworkFeature (under construction)&lt;/li&gt;&lt;li&gt;added UIFeature (under construction)&lt;/li&gt;&lt;li&gt;new CoreNetwork and Multiplayer addon wrapper subsystems for RakNet&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Please note the special RakNet licensing conditions. &lt;/b&gt;Basically, RakNet is not free if used for a commercial project (&lt;a href="http://www.jenkinssoftware.com/"&gt;http://www.jenkinssoftware.com/). Licensing details for 3rd party libs can be found on the Nebula3 documentation main page.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;Stuff I want to do soon&lt;/h3&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;fix the shader lighting code&lt;/li&gt;&lt;li&gt;add more shaders to bring the shader-lib up-to-par with N2&lt;/li&gt;&lt;li&gt;finish the CoreAnimation and Animation subsystems&lt;/li&gt;&lt;li&gt;design and implement proper skinned character rendering subsystem&lt;/li&gt;&lt;li&gt;add missing functionality to Audio subsystems (for instance sound categories) &lt;/li&gt;&lt;li&gt;make shaders SAS compatible so they work with tools like FXComposer&lt;/li&gt;&lt;li&gt;implement a proper resource-streaming system on the 360 (as proof on concept)&lt;/li&gt;&lt;li&gt;optimize messaging (use delegate-mechanism for dispatching, optimize message object creation, add double buffering behaviour to AsyncPort for less thread-synchronization overhead)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2321468467597118783?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2321468467597118783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2321468467597118783' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2321468467597118783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2321468467597118783'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/09/whats-new-in-september-nebula3-sdk.html' title='What&apos;s New in the September Nebula3 SDK'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7644679602438493486</id><published>2008-09-20T15:14:00.002+01:00</published><updated>2008-09-20T15:25:15.472+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula3'/><title type='text'>Adding functionality to threaded subsystems</title><content type='html'>Moving subsystems into their own thread introduces restrictions on how other threads can interact with the subsystem. It is no longer possible to simply invoke methods on objects running in the context of a threaded subsystem. The only way to interact with the subsystem is by sending messages to it. From a system design point-of-view this is a good thing. There's a very clear demarcation line defined by the message protocol to interact with the subsystem. It is pretty much impossible to invoke undocumented functionality from the outside and it is complicated to "accidently" use the subsystem's functionality in a way not intended by the subsystem's designer.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But of course those restrictions also have their dark side. All tasks which either require a lot of communication, or which require exact synchronization should better not be spread across threads. Although the messaging system is fast (and will remain an optimization hotspot) it is not free, it's not a good idea to send thousands (or even hundreds) of messages around per-frame. Also, a message sender should never wait for the completion of a message to work around the synchronization problem (at least not while the game loop is running), as this would pretty much nullify the advantage of running the subsystem in its own thread.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nebula3 offers a relatively simple way to add functionality which shall run in the context of a subsystem thread. The basic idea is to create a new message-handler class (which is running in the subsystem's thread) and a new set of messages which can be processed by an instance of the new handler-class.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We recently did this to add debug-visualization capability to Nebula3. We wanted to have a simple way to (a) render debug text, and (b) render shapes (cubes, spheres, etc...) to make it simple to render debug-visualizations from anywhere in Nebula3.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The whole system is split into 3 parts:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;The &lt;b&gt;front-end classes&lt;/b&gt; running on the client-side (client-side means: every thread other then the render thread):&lt;/li&gt;&lt;ul&gt;&lt;li&gt;the &lt;b&gt;Debug::DebugTextRenderer&lt;/b&gt; singleton offers text rendering&lt;/li&gt;&lt;li&gt;the &lt;b&gt;Debug::DebugShapeRenderer &lt;/b&gt;singleton offers shape rendering&lt;/li&gt;&lt;li&gt;both are thread-local singletons, each thread which wants to render debug text or shapes needs to instantiate those&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The &lt;b&gt;back-end classes&lt;/b&gt; running in the render-thread:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;CoreGraphics::TextRenderer&lt;/li&gt;&lt;li&gt;CoreGraphics::ShapeRenderer&lt;/li&gt;&lt;li&gt;these singletons implement the actual text- and shape-rendering functionality and are also platform-specific (under Windows, they use D3DX methods to do their jobs)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The &lt;b&gt;communication components&lt;/b&gt;:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;the Debug Render message protocol, this is a NIDL-XML-file (Nebula Interface Definition Language) which defines 2 messages: &lt;b&gt;RenderDebugText&lt;/b&gt; and &lt;b&gt;RenderDebugShapes&lt;/b&gt;&lt;/li&gt;&lt;li&gt;the &lt;b&gt;DebugGraphicsHandler&lt;/b&gt; object, whose class is derived from Messaging::Handler, runs in the render thread, and processes the above 2 messages &lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div&gt;This is how the system works:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;the main thread instructs the GraphicsInterface singleton (which creates and manages the render-thread) to add a DebugGraphicsHandler object (that's at least how it SHOULD work,  at the moment, the GraphicsHandler simply creates and attaches a DebugGraphicsHandler on its own)&lt;/li&gt;&lt;li&gt;client threads create one DebugTextRenderer and one DebugShapeRenderer singleton if they want to do debug visualization&lt;/li&gt;&lt;li&gt;a client-thread calls directly one of the DebugTextRenderer or DebugShapeRenderer methods to render text or shapes&lt;/li&gt;&lt;li&gt;the DebugTextRenderer and DebugShapeRenderer singletons collect a whole frame's worth of text elements and shapes and once per frame, create a single RenderDebugText and RenderDebugShapes message, so at most only 2 messages are sent into the render thread per-frame from each client-thread, not one message per shape and text element, that's a very important optimization!&lt;/li&gt;&lt;li&gt;Once per render-frame, the DebugGraphicsHandler processes incoming RenderDebugText and RenderDebugShapes by calling the CoreGraphics::TextRenderer and CoreGraphics::ShapeRenderer singletons&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's it basically. Nebula3 applications can add their own functionality to subsystem threads by following the described pattern.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With the first naive implementation we stumbled across an obvious problem: when the main-thread runs slower then the graphics thread, debug shapes and text would start to flicker, since the render thread would only receive render-debug-messages every other frame. So we had to add a way to identify shapes and text elements by their origin-thread-id, and keep them around until the next message comes in from the same thread, but this was a trivial thing to do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A positive effect is that debug visualization no longer needs to happen at a specific point in the render loop. This was a problem in Nebula2/Mangalore where classes had to provide an "OnRenderDebug()" method which was called by the rendering system from within the render loop. Instead debug visualization can now happen from anywhere in the code (although at the cost of some more memory and communications overhead, but especially debug visualizations is an area where convenience and ease-of-use is more important then raw performance).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;FYI, this is how the NIDL-file looks like, which defines the messages of the DebugRender protocol:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;table id="e1q." width="100%" cellpadding="3" cellspacing="0" border="0" class="zeroBorder" bgcolor="#fff2cc"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="100%"&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&amp;lt;Nebula3&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;    &amp;lt;Protocol namespace="Debug" name="DebugRenderProtocol"&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;!-- dependencies --&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;Dependency header="util/array.h"/&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;Dependency header="threading/threadid.h"/&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;Dependency header="coregraphics/textelement.h"/&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;Dependency header="debugrender/debugshaperenderer.h"/&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;!-- render text string on screen for debugging --&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;Message name="RenderDebugText" fourcc="rdtx"&gt;            &lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;            &amp;lt;InArg name="ThreadId" type="Threading::ThreadId"/&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;            &amp;lt;InArg name="TextElements" type="Util::Array&amp;lt;CoreGraphics::TextElement&gt;" /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;/Message&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;!-- render debug shapes --&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;Message name="RenderDebugShapes" fourcc="rdds"&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;            &amp;lt;InArg name="ThreadId" type="Threading::ThreadId"/&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;            &amp;lt;InArg name="Shapes" type="Util::Array&amp;lt;CoreGraphics::Shape&gt;" /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;        &amp;lt;/Message&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;    &amp;lt;/Protocol&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px"&gt;&amp;lt;/Nebula3&gt;    &lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;    &lt;/div&gt;&lt;div&gt;This will be compiled by the Nebula3 NIDL-compiler-tool into one C++ header and one source file (debugrenderprotocol.h and debugrenderprotocol.cc). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope to have a new source drop out "really-soon-now", so you can check for yourself what I'm actually talking about :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7644679602438493486?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7644679602438493486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7644679602438493486' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7644679602438493486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7644679602438493486'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/09/moving-subsystems-into-their-own-thread.html' title='Adding functionality to threaded subsystems'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4490217401053917794</id><published>2008-09-08T17:25:00.005+01:00</published><updated>2008-09-08T18:09:59.473+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Mercenaries 2</title><content type='html'>I'm currently having a lot more fun with Mercs 2 then I ever had with GTA4. Proves that blowing up shit is a lot more important then story in sandbox games. At least to me he. The game is a bit rough around the edges and has a number of minor bugs and glitches, but all the important stuff (controls, gun feedback, immersion, frequency of oh-shit moments) is much better then in GTA (IMHO of course). Battling a group of 3 or 4 heavy tanks in an army-occupied city only with RPGs and C4 is an absolutely exhausting experience, but so much fun with buildings crumbling left and right, tank shells and RPGs whizzing by and the distinctive sound of distant sniper fire over the general combat noise. Of course the player could opt to level the entire city with a few air strikes, but that would cost a lot of civilian lifes and wouldn't be well received by the Guerilla. And besides, air strikes are freaking expensive ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4490217401053917794?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4490217401053917794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4490217401053917794' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4490217401053917794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4490217401053917794'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/09/mercenaries-2.html' title='Mercenaries 2'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5556825715030597131</id><published>2008-08-12T16:23:00.007+01:00</published><updated>2008-08-12T17:59:39.208+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rant'/><title type='text'>OpenGL 3.0 (more like 2.2)</title><content type='html'>Oh the drama! The long-awaited &lt;a href="http://www.khronos.org/news/press/releases/khronos_releases_opengl_30_specifications_to_support_latest_generations_of/"&gt;OpenGL 3.0&lt;/a&gt; spec has been released today after years of fruitless discussions in the ARB and Khronos Group, and - surprise - it is NOT the fresh and clean re-write that was promised, but instead only a minor release with a few extensions moved into the core feature set, and a few old features marked as depreciated. Nobody but the design commitee exactly knows what justifies the version number jump other then pretending progress.&lt;br /&gt;&lt;br /&gt;In the old days of DX3 and DX5 I was a big fan of OpenGL, which was so much cleaner and easier to use compared to D3D. I still remember the horror of porting Urban Assault to DX5 in '97). I despised how Microsoft was completely rewriting the DirectX API every year. In hindsight that was their best decision, DX didn't have to care about old baggage and slowly got better until the excellent DX9, while the once elegant OpenGL was buried under a heap of vendor-specific extensions over the years, resulting in the mess it is today.&lt;br /&gt;&lt;br /&gt;Somewhere inside I'm a bit sad to see OpenGL slowly dwindle into oblivion, on the other hand I didn't really care about it for the last 4 or 5 years (I think I stopped caring when I attempted to write an OpenGL renderer for Nebula2 and realized that I had to use a dozen-or-so extensions just to get DX9's core features).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5556825715030597131?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5556825715030597131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5556825715030597131' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5556825715030597131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5556825715030597131'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/08/opengl-30-more-like-22.html' title='OpenGL 3.0 (more like 2.2)'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7964261146009096709</id><published>2008-08-02T12:45:00.004+01:00</published><updated>2008-08-02T14:36:29.880+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>MGS4</title><content type='html'>*** WARNING, SPOILERS AHEAD ***&lt;br /&gt;&lt;br /&gt;Alright, first play-through done. Debriefing showed 20 hours playtime. Overall an amazing experience, even if it felt like only one third of it was actual game-play and the rest was watching cutscenes. The game starts really slow and in the first and second chapter I actually had to motivate myself to continue playing. Then with the ending cutscene of chapter 3, the story suddenly becomes interesting and the rest of the game is an amazing ride, only problem is, there are only 2 chapters left at this point.&lt;br /&gt;&lt;br /&gt;The presentation of the game during cut-scenes is jaw-dropping. The quality of the characters models, facial animation, motion capture performances is almost unbelievable. The direction and story-telling of the cut-scenes provides better entertainment then most good action movies. Unfortunately, for every one scene of pure awesomeness (basically every scene with Old Snake AND Liquid Ocelot) there two scenes which are outright cheesy and a real pain to endure.&lt;br /&gt;&lt;br /&gt;The story wraps up all the events of the previous MGS games and can be a bit hard to follow since from time to time, the story-telling switches into some sort of white-board-mode and floods the player with details (which provide interesting background information but would IMHO be better if told through codec conversations). The other problem is, that the back-story of EVERY F*CKING PERSON which EVER showed up in ANY MGS game is brought to its end, turning parts of the story into a gigantic soap-opera. I think 4 or 5 hours of the cutscenes could have been removed and I wouldn't have missed a thing.&lt;br /&gt;&lt;br /&gt;In its core, MGS4 tells the story of 2 old men, Solid Snake (the hero from MGS1, and clone of Naked Snake from MGS3), who's suffering from accelerated aging programmed into his genes (as far as I understood that part of the story), and Liquid Ocelot, a chimera of Liquid Snake and Revolver Ocelot. Snake is portraied as a cynical, pragmatic asshole, which really makes him a likeable protagonist. But the real hero of the game (to me) is Ocelot, he's an old man, just as Snake, but has aged naturally, and he (or better his Liquid Snake part) has all the energy and vision left which Snake seems to have lost long ago. In the end it's all about handing the world over to the next generation (shame that thist next generation mainly consists of whiners and wimps).&lt;br /&gt;&lt;br /&gt;On to game-play: This is the disappointing part IMHO, which is a real shame since MGS4 is still considered a game, not a movie. The core sneaking elements are the same as in MGS2 and MGS3, which is of course a good thing. You can still hide in lockers or under cardboard boxes, shake knocked-out or dead enemies to loot them, and the camouflage element from MGS3 is also there, but now in its science-fiction version as the octocamo suit (basically, adaptive optical and infrared camouflage).&lt;br /&gt;&lt;br /&gt;The survival elements from MGS3 have been removed, and replaced with shooter gameplay, and that's where I still have my biggest problem with because a sneaking element has been removed in favour of an action-oriented gameplay element. I'm a big shooter fan so that wouldn't be much of a problem for me IF PROPERLY IMPLEMENTED. Problem is, the shooting stuff is only very basic and for a shooter, the controls feel extremely awkward. If gun handling would only be half as good as in good tactical shooters like Rainbow Six Vegas I would be sold, but unfortunetaly it's far from it. Especially cover and firing from cover have been evolved dramatically since the times of MGS2 and MGS3, but in MGS4, firing from cover is still as awkward as in these old games. Also, the big number of guns offered to the player is kinda useless. There's no real reason to choose a submachine gun over an assault rifle. A sniper rifle is just as easy to use close-range as any other gun. An assault rifle with an optical sight is just as good as a sniper rifle over long range, because the levels are relatively small anyway.&lt;br /&gt;&lt;br /&gt;I wish the developers would have put all the work which has gone into the shooters aspects into new sneaking elements instead. Compared to the last Splinter Cell, the game-play of MGS has been falling behind. Look at all the Bond-gadgets Sam Fisher has at its disposal, or all the ways Fisher can approach a door to investigate what's behind it before sneaking into a room... (man, speaking of Splinter Cell - I think I need to re-play Double Agent soon...).&lt;br /&gt;&lt;br /&gt;But even if I don't particularly like the direction MGS has taken, it's still truly exceptional entertainment and one of the best games of the current console generation. And I think it was the right decision to put Snake to rest and with him the MGS series, since at least I am ready for some fresh wind in the sneaking genre (although it seems there will be lots of trial-and-error ahead as the S.C.Conviction and Assassins Creed "debacles" show).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7964261146009096709?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7964261146009096709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7964261146009096709' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7964261146009096709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7964261146009096709'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/08/mgs4.html' title='MGS4'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4391556069707843155</id><published>2008-07-29T11:55:00.005+01:00</published><updated>2008-07-29T12:19:49.998+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>PSN hmm...</title><content type='html'>I have removed the PSN "Portable ID" on the left side. Seems like it's just a static display for my user name and avatar picture doh... And I can't believe that Sony doesn't let me download (buy even!) additional gamer pictures from PSN (or I simply didn't find them? even after the re-design it isn't exactly easy to find stuff on the PSN shop, even though there's not THAT much stuff there). I'd really love to have an MGS4 gamer pic. It's all those little "un-important" things which make me appreciate the online-integration of the 360 (on the other hand, if I had gone straight from the PS2 to the PS3 I probably wouldn't even care, but the 360 really has spoiled me). Sony really needs to get all this simple and obvious stuff fixed first instead of wasting their time and resources on Home IMHO.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4391556069707843155?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4391556069707843155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4391556069707843155' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4391556069707843155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4391556069707843155'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/07/psn-hmm.html' title='PSN hmm...'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4861108516327878702</id><published>2008-07-25T09:24:00.003+01:00</published><updated>2008-07-25T10:04:21.111+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Kept ya waiting huh?</title><content type='html'>Sooo I finally bought a PS3 yesterday. MGS4 did it (I basically bought a PS2 just for MGS3, so this was inevitable). My local GameStop was sold out completely (the guy there said he won't get any new PS3's until the new 80GB model comes out end of August). MediaMarkt still had one MGS4 bundle left so I took this one.&lt;br /&gt;&lt;br /&gt;First impressions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;OMG its huge! Ok, power supply is integrated, but the 360 looks tiny compared to this thing.&lt;/li&gt;&lt;li&gt;I was actually planning to wait for the white PS3 (black entertainment devices are plain ugly IMHO) but it looks like it will never arrive in Europe.&lt;/li&gt;&lt;li&gt;System and WLAN setup was fast and flawless.&lt;/li&gt;&lt;li&gt;Surprisingly, picture quality is worse on my TV then my 360. I have an 2 year old 32" LCD Sony Bravia, and have the PS3 connected through HDMI. The 360 is connected through VGA. There's a lot of edge aliasing going on in the PS3 picture. I suspect that's because the VGA connection runs at the native display resolution (1280x768 or so), while the 720p HDMI connection has a non-native display resolution so that the TV's scaler kicks in. Basically looks the same like when I had connected the 360 through component. Still I would think that connecting one Sony device to another Sony device through a digital connection would generate a better picture.&lt;/li&gt;&lt;li&gt;During a game, the TV signal is lost from time to time (maybe once per hour for about 2 seconds). WTF? I've read about this in forums but thought this would only happen with some obscure TV's. Again this is a Sony TV and a Sony console. This definitely didn't happen when I had my 360 running through HDMI.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The XMB looks slick and feels much more responsive compared to the 360's dashboard.&lt;/li&gt;&lt;li&gt;Way too many system settings... half of which don't interest me at all (mouse sensitivity???)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The system didn't notify me that a software update is available. How is a typical user supposed to notice that he isn't uptodate?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Not impressed by the web browser, feels terribly slow and unusuable without a mouse...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Downloading the new firmware took FOREVER (20 minutes or so?), and displayed another progress bar for installation which took another couple of minutes. I don't remember waiting for more then 3 minutes for a system update on the 360...&lt;/li&gt;&lt;li&gt;MGS4 starts: ugh more installation... this isn't funny.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Start screen with all those little flowers looks REALLY messy on my TV...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ok, WTF is this David Hayter interview shit before starting a new game?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Hmm, ingame graphics isn't quite as impressive as I remember from the trailers...&lt;/li&gt;&lt;li&gt;Snake's character model looks really great though.&lt;/li&gt;&lt;li&gt;Adaptive camo is nice.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;2 hours later...&lt;/li&gt;&lt;li&gt;MGS4 doesn't know whether it want's to be a shooter or a sneaker... definitely too much emphasis on guns and shooting, which would be fine with me if shooter controls wouldn't be horribly broken, getting out of that abandoned hotel with the hot chick's team was an extremely frustrating experience&lt;/li&gt;&lt;li&gt;story didn't exactly grab me so far... cutscenes are cringe-worthy when they try to be funny&lt;/li&gt;&lt;/ul&gt;Guess MGS4 needs to grow on me. When I launched MGS3 I was immediately fascinated and couldn't stop playing. This didn't happen so far with MGS4. Will post more impressions when I finished the game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4861108516327878702?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4861108516327878702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4861108516327878702' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4861108516327878702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4861108516327878702'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/07/kept-ya-waiting-huh.html' title='Kept ya waiting huh?'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7400083386330430708</id><published>2008-07-22T18:23:00.002+01:00</published><updated>2008-07-22T19:02:23.733+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Ninja Gaiden DS</title><content type='html'>Ninja Gaiden Dragon Sword for the Nintendo DS is finally available in Germany (&lt;span style="font-weight: bold;"&gt;D&lt;/span&gt;ragon &lt;span style="font-weight: bold;"&gt;S&lt;/span&gt;word - DS - gettit?). How the game is controlled using the stylus is astonishing, breathtaking, eye-opening, dare I say: revolutionary.&lt;br /&gt;&lt;br /&gt;They nailed the controls, plain and simple. Just as the 2 Xbox games, the DS version is all about rythm, but instead of hitting button combos, playing NG DS is more like painting a picture with a brush. A few well-placed "brush strokes" here and there, a few taps over there, and another group of Spider Clan ninjas are history. Something complex like an Izuna Drop is simply done by a down-up-up-stroke over the enemy (the first down-stroke is a more-or-less normal sword attack, the first up-stroke launches the enemy into the air, and the second upstroke has Ryu jump into the air, grab the enemy and whirl it into the ground.&lt;br /&gt;&lt;br /&gt;The graphics are beautiful for what the DS can do. The backgrounds are 2D bitmaps, but give a good 3D-ish illusion since the 3D characters can move into the screen with the correct perspective projection.&lt;br /&gt;&lt;br /&gt;Best DS game in a while, shame that it got so little attention from the DS crowd.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7400083386330430708?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7400083386330430708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7400083386330430708' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7400083386330430708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7400083386330430708'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/07/ninja-gaiden-ds.html' title='Ninja Gaiden DS'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5201833310442558451</id><published>2008-07-20T16:42:00.007+01:00</published><updated>2008-07-20T17:44:29.613+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>10 Years After</title><content type='html'>Andreas, an old friend of mine, noticed that &lt;a href="http://www.microsoft.com/games/urbanassault/"&gt;Urban Assault&lt;/a&gt; went Gold (or RTM - Release To Manufacture as it was called at Microsoft at that time) on July 13th 1998, almost exactly 10 years before Drakensang went Gold (which was at the 10th of July 2008). He even sent me the original anouncement mail I sent back to Germany. Andreas and I had been "stationed" over at Seattle at that time to apply the final fixes and polish to UA, since flying the programmers over to NA was probably more convenient in 1998 then FTP'ing complete daily game builds over ISDN.&lt;br /&gt;&lt;br /&gt;Apart from the usual post-project cleanup stuff I can now start to work on new and exciting technology stuff again, improving our tool-chain, continue working on Nebula3, and dust off those Wii and 360 devkits which probably feel a bit neglected due to our focus on finishing Drakensang.&lt;br /&gt;&lt;br /&gt;We're also a licensed PS3-developer now, a N3 port hasn't started yet but from looking through the SDK docs the programming environment doesn't seem to be too bad. The underlying philosophy or "style" is a bit different then the 360 SDK (just like for instance Win32 has a different style then Unix). But all in all the PS3 SDK looks complete and actually quite usable. It's also quite obvious from looking through the release note history that the PS3 SDK has improved a lot since the PS3 launch. I think it will be relatively easy to get "something" up and running on the PS3, squeezing the last bit of performance out of the bitch however will be something completely different I'm sure ;)&lt;br /&gt;&lt;br /&gt;The Dead Rising port to the Wii might be the most interesting news I took out of E3. It made me play the 360 version again, and this is one of those game which get better and better over time.&lt;br /&gt;&lt;br /&gt;I totally underestimated the importance of the books one can find in the different book stores. In the past I ignored them because they take up valuable inventory slots. But what they actually do is they make every single slot much more valuable. For instance there is a book which triples the time edged weapons can be used until they break, and another which triples the usage time of items from home-improvement-stores. And the effects actually stack. For instance the mini-chainsaws which are unlocked after killing the clown-psycho (pretty much the most powerful melee weapons in the game) fall under both categories!&lt;br /&gt;&lt;br /&gt;The Wii port of Dead Rising makes immediate sense with all the special attacks or shaking off zombies for instance. These should translate very well to waggle. I'm concerned though about the number of zombies. It's just not Dead Rising without hundreds of zombies on screen. The first batch of Wii screens have a suspicious lack of zombies in them...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5201833310442558451?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5201833310442558451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5201833310442558451' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5201833310442558451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5201833310442558451'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/07/10-years-after.html' title='10 Years After'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1082564263216519847</id><published>2008-06-27T16:26:00.005+01:00</published><updated>2008-06-27T18:11:28.093+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Status Update</title><content type='html'>We're currently in release candidate mode for &lt;a href="http://www.radonlabs.de/gamesdrakensang.html"&gt;Drakensang &lt;/a&gt;which basically means we're more or less on standby until QA hits the alarm button because they found a show-stopper bug. The good thing is that I can spend most of my time at work actually playing the game from start to finish. Obviously I'm biased, but a truly wonderful game it has become. Of the games I've been involved with in my life, Drakensang is probably the one I am most proud of.&lt;br /&gt;&lt;br /&gt;After Drakensang has gone gold I think I can spend more time with Nebula3 and the blog again.&lt;br /&gt;&lt;br /&gt;In stark contrast to Drakensang I've spent the last couple of evenings at home mainly with Ninja Gaiden 2. I did a normal play-through on Path Of The Warrior, one Dragon Sword weapon run on Acolyte (which really was too easy), and am currently half-way through a Lunar Staff weapon run on Warrior with many many play-throughs to follow.&lt;br /&gt;&lt;br /&gt;Coming straight from Ninja Gaiden Black I had some trouble to adapt to the new style of the game. In the original, fights are against 3 or 4 enemies at once. In NG2 a typical fight is against 10..15 enemies at once. The combo and hit-recovery timing is a bit different in NG2, which made the control feel sluggish to me at the beginning. Also, the polishing grade couldn't be more different. NGB was probably one of the most polished games in history, while the lack of polish in NG2 is quite apparent unfortunately (yes, the camera does indeed have some issues, I had 2 freezes so far, and the game goes into some sort of slow-motion-mode in heavy fighting situations).&lt;br /&gt;&lt;br /&gt;But despite these flaws NG2 still trumps any other fighting game I have played so far because the rest is so f*cking great. The core game mechanics are so extremely carefully tuned (and fine-tuned compared to NGB) that the laughable story and less-then-stellar boss-fights are simply not that important. NG2 shines where the player spends the most time with: fighting hordes of ninjas and monsters. The actual combat is so intense and incredibly satisfying that I want to start a new game immediately after finishing the last. There is one special moment in the game involving a staircase and maybe 100 or 200 ninjas which is simply jaw-dropping (and is probably my most favourite gaming moment of all time).&lt;br /&gt;&lt;br /&gt;If there ever was a flawed diamond among games, it is Ninja Gaiden 2. Even with its flaws it is a really exceptional game, but if Itagaki and his team of ronin find a way to improve the game as they did with Ninja Gaiden Black the result would be ultimate perfection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1082564263216519847?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1082564263216519847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1082564263216519847' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1082564263216519847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1082564263216519847'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/06/status-update.html' title='Status Update'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2013142906834895700</id><published>2008-06-11T16:44:00.003+01:00</published><updated>2008-06-11T17:30:35.128+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>NG2 (YES!!!)</title><content type='html'>I finally got the game! I ordered the UK version because NG2  isn't available in Germany anyway. I just rushed quickly through the first 2 chapters yesterday evening and holy shit this game is epic. DMC4 was fun, but NG2 is simply on a whole different level in every aspect (yeah, I'm a biased Ninja Gaiden fanboi but anyway...).&lt;br /&gt;&lt;br /&gt;One thing I noticed immediately is that the rythm of the game is a bit different then Ninja Gaiden Black. It was a bit harder for me to pull off an Inazuna Drop in the beginning. Ryu's control feels a bit heavier (or one could say, a little bit more realistic). And Jesus are the enemies aggressive right from the beginning. Hold a block for more then 2 seconds and the bastards will rip you apart :o) But due to the new partial life regeneration and plenty of save points, the game feels a bit easier in Way Of The Warrior compared to NGB on Normal difficulty (so far at least).&lt;br /&gt;&lt;br /&gt;The gore is a bit too over the top for my taste. Nothing against some blood-spilling, but I felt a bit uneasy after I had reduced a group of 10..20 spider-clan ninjas into a bloody heap of arms, legs and torsos and some glibberish things which I don't want to inspect too closely. At least for the first time. Afterwards it becomes kind of a routine. This is basically the game version of Kill Bill (wow, how cool would that be: playing as a yellow-clad Uma Thurman through NG2...).&lt;br /&gt;&lt;br /&gt;I love this game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2013142906834895700?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2013142906834895700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2013142906834895700' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2013142906834895700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2013142906834895700'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/06/ng2-yes.html' title='NG2 (YES!!!)'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7036807127493536198</id><published>2008-05-27T10:45:00.004+01:00</published><updated>2008-05-27T11:00:31.575+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>What Camera Issues?</title><content type='html'>OMG I can't believe reviewers still bitch about the camera in Ninja Gaiden 2. If it's the same as in NG1 (which they complained about as well when it came out) then it's just perfect. Just tap the right trigger and the camera snaps back behind Ryu. That's the secret to successful camera control in Ninja Gaiden ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7036807127493536198?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7036807127493536198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7036807127493536198' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7036807127493536198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7036807127493536198'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/05/what-camera-issues.html' title='What Camera Issues?'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5722593440160451564</id><published>2008-05-13T17:37:00.002+01:00</published><updated>2008-05-13T17:40:48.384+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Slides to my Quo Vadis presentation</title><content type='html'>Here are the slides to the presentation I gave at the Quo Vadis developer conference last week in Berlin. It's all in German, but it has some pretty pictures in it ;) Unfortunately the Save-As-PDF feature in Powerpoint doesn't embed the video files (only pictures of them), so I packed everything into a zip archive.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.radonlabs.de/internal/drakensang_nebula_quovadis_2008.zip"&gt;Here's the link.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5722593440160451564?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5722593440160451564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5722593440160451564' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5722593440160451564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5722593440160451564'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/05/slides-to-my-quo-vadis-presentation.html' title='Slides to my Quo Vadis presentation'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-833252935972799875</id><published>2008-05-12T12:47:00.003+01:00</published><updated>2008-05-12T13:41:48.600+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>More Memory Debugging Notes</title><content type='html'>A few memory debugging tips which I found useful during the past few weeks:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Always look at ALL process heaps when doing memory debugging.&lt;/span&gt; Turns out we still had a rather obvious memleak in Drakensang. It didn't show up in our own memleak dumps because it happened in an external heap created by SpeedTree, and we can only track allocations going through our own memory subsystem and through the CRT. After dumping a summary of all heaps returned by GetProcessHeaps() before and after loading a level one of the "external" heaps showed a memleak of up to 10 MB per level-load! The heap disappeared after compiling without SpeedTree-support, so the culprit was easy to identify (of course it wasn't SpeedTree's fault, but a bug in our own tree instancing code, which was fixed in half an hour, and admittedly it was a very obscure special case to not have showed up as a memleak in our own dumps as well).&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Use memory allocation hooks in 3rd party libs if they support it.&lt;/span&gt; In fact I wish all libs would support a mechanism to re-route memory allocations to my own routines, if only for debugging reasons. There's no way to track memory allocations happening inside XACT for instance (that I'm aware of?!).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Write an automatic stress test for your app early in the project. &lt;/span&gt;We have started a while ago to run continuous playthrough sessions with a hot-seat system where our testers hammer the same game-session 24/7. The more subtle memory leak bugs often only trigger after 10 or 20 hours of continuous playtime. Despite this continuous testing I also wrote a little stress test mode, where the game loads a level, lets the level run for 30 seconds and then load another level, ad infinitum over night. This may amplify bugs which happen during load time, and may attenuate bugs happening during normal game play (the SpeedTree related memleak mentioned above went critical much earlier in the stress-test as in normal gameplay-sessions). A water-proof generic record/replay mechanism in the engine would be helpful as well (we don't have that in Drakensang, but this may be a feature we might look into in the future).&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;A fixed memory layout is actually helpful on the PC as well.&lt;/span&gt; Drakensang doesn't have this, but I'm becoming more and more a fan of a fixed memory layout. Set aside N megabytes for C++ objects, another chunk of memory as temporary load/save buffer, fixed memory buffers for the different resource types, allocate those blocks at the beginning of the game either as non-growable heaps, or as pre-allocated virtual memory blocks with custom-taylored memory management - and let the game crash if any of the heaps is exhausted. The main reason why this is a good idea is not so much finding memory leaks, but to prevent resource usage to grow out of control during development.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I have collected a lot of ideas for the Nebula3 memory subsystem which I will play around with as time permits.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-833252935972799875?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/833252935972799875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=833252935972799875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/833252935972799875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/833252935972799875'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/05/more-memory-debugging-notes.html' title='More Memory Debugging Notes'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5671315616778126206</id><published>2008-05-04T16:57:00.007+01:00</published><updated>2008-05-04T17:35:21.744+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>GTAIV</title><content type='html'>Dammit I wish I had more time to play GTA... In the first hour or two, the game actually wasn't the jaw-dropper I had expected (other games on the 360 definitely look better, and the walking controls are just as shitty as in the old GTA's). But boy has the game grown on me after a little while... there's not one session where I don't discover some hilarious shit to do in the game... there's so much attention to detail in the tiniest, most forgotten and dark corners of Liberty City... And some of the missions I have encountered so far are simply epic (the gunwork has improved dramatically over GTA3:SA, although the new cover system could have used a bit more work). Some of the elements I liked in San Andreas have been removed unfortunately (like the character development stuff), but all the new features and improvements definitely compensate for the loss. R* have delivered again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5671315616778126206?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5671315616778126206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5671315616778126206' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5671315616778126206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5671315616778126206'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/05/gtaiv.html' title='GTAIV'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5020143699289829549</id><published>2008-04-28T10:43:00.005+01:00</published><updated>2008-04-28T11:08:25.358+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>COD4 DLC woes...</title><content type='html'>Here's an interesting side-effect of the COD4 map pack: ever since I downloaded the map pack my K/D-ratio started to suffer terribly. Once I deleted the map pack from my HD the ratio immediately improved. Looks like the map-pack was mainly purchased by hardcore players, so that there are not enough noob players like me available for fair match-making. So the DLC actually made the game less enjoyable for me. Well, I didn't like Chinatown anyway ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5020143699289829549?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5020143699289829549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5020143699289829549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5020143699289829549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5020143699289829549'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/04/cod4-dlc-woes.html' title='COD4 DLC woes...'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-8284984893763018596</id><published>2008-04-20T14:14:00.001+01:00</published><updated>2008-04-20T14:15:31.257+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Memory Issues</title><content type='html'>The 2 most critical issues with dynamic memory allocation seem to be memory leaks and memory fragmentation. While memory leaks can be discovered and fixed easily, memory fragmentation is harder to come by since it usually only shows up when the application runs for many hours. At some point, allocation of large memory blocks may fail even though the total amount of free memory is more then enough to satisfy the request. I have recently added some counter-measures to Drakensang, which I have ported over to Nebula3 during the last 2 hours. The basic idea is to go away from the general Memory::Alloc()/Memory::Free() and to group allocations by usage pattern into different heaps, so that small, large, short-lived or long-lived memory blocks are not allocated all from the same heap.  Nebula3 now defines various global HeapTypes, which need to be provided as arguments to the Memory::Alloc() and Memory::Free() functions. Platform ports of Nebula3 are free to define additional platform-specific heap types, as long as only platform-specific code uses those new types. The platform-specific code also has full control over the initialization of the global heaps (like the initial heap size, or whether the heap is allowed to grow or not), which is especially important for console platforms with their restricted amount of memory and no page-file-swapping.  For now I have arbitrarily defined the following heap types:  &lt;ul id="z8s9"&gt;&lt;li id="aaqw"&gt;&lt;span id="h0u2"&gt;&lt;b&gt;DefaultHeap&lt;/b&gt;&lt;/span&gt;: for stuff that doesn't fit anywhere else&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="j8vk"&gt;&lt;b&gt;ObjectHeap&lt;/b&gt;&lt;/span&gt;: for RefCounted objects (this may be split into more HeapTypes in the future)&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="b8x6"&gt;&lt;b&gt;SmallBlockHeap&lt;/b&gt;&lt;/span&gt;: general heap for small allocations&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="l1yk"&gt;&lt;b&gt;LargeBlockHeap&lt;/b&gt;&lt;/span&gt;: general heap for "large" allocations (several megabytes)&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="jyvs"&gt;&lt;b&gt;ResourceHeap&lt;/b&gt;&lt;/span&gt;: for long-lived resource data, like animation keys&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="vq3b"&gt;&lt;b&gt;ScratchHeap&lt;/b&gt;&lt;/span&gt;: for short-lived memory blocks&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="kz.0"&gt;&lt;b&gt;StringHeap&lt;/b&gt;&lt;/span&gt;: for string-data&lt;/li&gt;&lt;li id="rndj"&gt;&lt;span id="ws7l"&gt;&lt;b&gt;StreamDataHeap&lt;/b&gt;&lt;/span&gt;: used by classes like MemoryStream or ZipFileStream&lt;/li&gt;&lt;/ul&gt; Those heap types may change in the future, I'm not sure yet, whether these are too many or too few types. I'll add some more status information to the memory HTTP debug page handler with statistics data about the different heap types, so it should be easy to see whether this configuration is good or not. Also, the Nebula3 code doesn't have that many calls to Memory::Alloc() or Memory::Free() (around 20..30 or so), so it's relatively easy to try out different usage patterns.  Of course it's still possible to create a special local heap using the Memory::Heap class.  On a side note: as you may have noticed, my posting frequency has suffered a lot recently. The reason is that I'm now 110% focused on Drakensang, there's just not enough time left to do a lot of work on N3 or on the blog. Don't expect this to change until around mid-July :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-8284984893763018596?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/8284984893763018596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=8284984893763018596' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8284984893763018596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8284984893763018596'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/04/memory-issues.html' title='Memory Issues'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2182354172967109629</id><published>2008-03-31T17:51:00.003+01:00</published><updated>2008-03-31T18:07:45.651+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>In Oblivion</title><content type='html'>I can't believe I started playing Oblivion again. I finally want to finish the main quest, last time I played through nearly all guild quests and then didn't have enough motivation left to go on with the main story... I was immediately sucked into the game again. Dungeon crawling is where Oblivion really shines, even more then Morrowind (which I still consider the better overall game). I have created a new dark-elf nightblade which I'm playing as a stealthy magic-wielding, arrow-shooting bad-ass assassin :o)&lt;br /&gt;&lt;br /&gt;I also started to play around a bit with &lt;a href="http://www.w3.org/TR/SVG12/"&gt;SVG&lt;/a&gt;, since I was looking for a cheap way to render diagrams for the Nebula3 debugging and profiling subsystem. I'll go into more details in a later post, but let me just say that SVG kicks ass and is exactly what I was looking for. Fun-fact: the only browser that can't render SVG out of the box is IE7 (Firefox, Opera and Safari are fine).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2182354172967109629?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2182354172967109629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2182354172967109629' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2182354172967109629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2182354172967109629'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/03/in-oblivion.html' title='In Oblivion'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3276573137316972033</id><published>2008-03-19T17:20:00.002+01:00</published><updated>2008-03-19T17:25:03.440+01:00</updated><title type='text'>Complexity</title><content type='html'>Just came across this citation on Slashdot:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"Any third-rate engineer or researcher can increase complexity; but it takes a certain flair of real insight to make things simple again."&lt;/span&gt; - E.F.Schumacher.&lt;br /&gt;&lt;br /&gt;Every programmer and game designer should bow before these mighty words of wisdom. Guess I need to read his book "Small Is Beautiful" now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3276573137316972033?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3276573137316972033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3276573137316972033' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3276573137316972033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3276573137316972033'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/03/complexity.html' title='Complexity'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5253403435892670322</id><published>2008-03-16T14:00:00.002+01:00</published><updated>2008-03-16T14:49:35.147+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Gaming Weekend</title><content type='html'>I'm not feeling very productive this weekend, might have to do with the shitty weather in Berlin...just the right weather to stay at home and play some games. I bought Bully for my 360 last week. I didn't play the original on the PS2, and although I read that the game "might freeze on some older consoles" I gave it a try. And guess what, it froze on me about 2 hours into the game, loosing at least 1 hour since the last save. I'm waiting now for the patch RockStar promised should come last week, since the game really looks like fun. Lousy certification job though, this bug shouldn't have slipped through.&lt;br /&gt;&lt;br /&gt;Played through the first chapter of Rainbow Six Vegas again... and I must say the game hasn't aged very well. The graphics is a bit too dirty, it's very hard to make out enemies against the background at least in the Mexican setting in the beginning. There's still no better cover system in any other game though, but I had a hard time to adapt to the controls again (blew myself up several times because 'B' is 'throw grenade' instead of crouch). I think it was the right decision to make the graphics in Vegas 2 that much cleaner, even though I was turned off at first by the "cartoony" look of the screenshots.&lt;br /&gt;&lt;br /&gt;After that mildly frustrating experience I played some more Ninja Gaiden Black on Hard difficulty. I finally want to kick Alma's ass. This game just gets better the more you play it. The structure of the game is very different on Hard difficulty. There are new enemies, items are distributed differently in the world, you get weapons and their upgrades only much later, and the boss fights are much more challenging because the bosses are now accompanied by minions. It is amazing how well balanced the rock-scissor-paper system in Ninja Gaiden is. A different weapon can make a subtle but very important difference for a specific enemy type. For instance, at first glance, the new cat-demons in hard difficulty just look like a more annoying version of the Black Spider Ninjas, but while the ninjas can be controlled very nicely with the Lunar staff, I feel much more comfortable fighting the cat-demons with the nunchuk (need to do some experimentation with the Vigorian Flail though). Hard difficulty also forces you to learn blocking, jumping and rolling much more efficiently to avoid attacks. I recently downloaded Ninja Gaiden as an Xbox Original title even though I also own the disc version. Not having to swap discs for a quick round of Ninja Gaiden fun is well worth the 1200 points IMHO :)&lt;br /&gt;&lt;br /&gt;I also played an hour of Crackdown. This game is still so much fun... I was playing around with some of the more advanced stuff I didn't use during my earlier play-throughs. For instance, specifically aiming for body- or car-parts (head-shots with the sniper-rifle over insane distances, or causing havoc on the highways by blowing up the gas-tank or tires of passing vehicles). I read somewhere that GTA4 will use a similar targeting system, if true this would be great, I really started to appreciate the added targeting functionality in Crackdown, especially when playing a bit more tactical instead of blowing up the whole perimeter Terminator-style.&lt;br /&gt;&lt;br /&gt;I finally ended the day with a few rounds of COD4 multi-player. I'm now on my second prestige-round. I guess I have finally finished my transition from a keyboard/mouse- to a gamepad-FPS player. I can pull off shit with the gamepad now which I deemed impossible one year ago :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5253403435892670322?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5253403435892670322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5253403435892670322' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5253403435892670322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5253403435892670322'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/03/gaming-weekend.html' title='Gaming Weekend'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2269079327438611392</id><published>2008-03-15T14:47:00.005+01:00</published><updated>2008-03-15T15:18:42.818+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Vertex Component Packing</title><content type='html'>I finally got around to optimize vertex component sizes for Drakensang. A typical vertex (coords, normal, tangent, binormal, one uv-set) is now 28 bytes instead of 56 bytes, a light-mapped mesh vertex (2 uv-sets) is now 32 bytes instead of 64, and a skinned vertex has been reduced to 36 bytes instead of 88. With this step I have finally burned all DX7-bridges, all our projects have a 2.0 minspec now (since Radon Labs also does casual titles, we had to support Win98 and DX7 for much too long). As a result, the size of all mesh resources in Drakensang has been reduced from from a whopping 1.2 GByte down to about 650 MByte. This also means reduced loading times and better vertex-through-put when transferring vertex data to the graphics chip. Some vertex components need to be scaled to the proper range in the vertex shader, but this is at most one multiply-add operation per component.&lt;br /&gt;&lt;br /&gt;I also implemented support for the new vertex formats in Nebula3. N3 always had support for packed vertex components, so all I had to do was to add a few lines to the legacy NVX2 mesh loader and fix a few places in the vertex shaders for unpacking normals and texcoords.&lt;br /&gt;&lt;br /&gt;Here's how the vertex components are now packed by default:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Position: Float3 (just as before)&lt;/li&gt;&lt;li&gt;Normal, Tangent, Binormal: UByte4N (unsigned byte, normalized)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;TexCoord: Short2 as 4.12 fixed point&lt;/li&gt;&lt;li&gt;Color: UByte4N&lt;/li&gt;&lt;li&gt;Skin Weights: UByte4N&lt;/li&gt;&lt;li&gt;Skin Joint Indices: UByte4&lt;/li&gt;&lt;/ul&gt;Normals, tangents and binormals and tex-coords need an extra unpacking instruction in the vertex shader. Skin weights need to be "re-normalized" in the vertex shader because they loose too much precision:&lt;br /&gt;&lt;br /&gt; float4 weights = packedWeights / dot(packedWeights, float4(1.0, 1.0, 1.0, 1.0));&lt;br /&gt;&lt;br /&gt;This will make sure that the components add up to 1.0. In case you're wondering, the dot product is equivalent with s = (x + y + z + w), it's just much more efficient, because the dot product is a native vertex shader instruction (although I must confess that I didn't check yet whether fxc's optimizer is clever enough to optimize the horizontal sum into a dot product automatically).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2269079327438611392?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2269079327438611392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2269079327438611392' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2269079327438611392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2269079327438611392'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/03/vertex-component-packing.html' title='Vertex Component Packing'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1217510401325801990</id><published>2008-03-05T12:03:00.002+01:00</published><updated>2008-03-06T11:57:05.744+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Nebula3's Multithreaded Rendering Architecture</title><content type='html'>Alright! The Application Layer is now running through the new multithreaded rendering pipeline.&lt;br /&gt;&lt;br /&gt;Here's how it works:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The former Graphics subsystem has been renamed to InternalGraphics and is now running in its own "fat thread" with all the required lower-level Nebula3 subsystems required for rendering.&lt;/li&gt;&lt;li&gt;There's a new Graphics subsystem running in the application thread with a set of proxy classes which mimic the InternalGraphics subsystem classes.&lt;/li&gt;&lt;li&gt;The main thread is now missing any rendering related subsystems, so trying to call e.g. RenderDevice::Instance() will result in a runtime error.&lt;/li&gt;&lt;li&gt;Extra care has been taken to make the overall design as simple and "fool-proof" as possible.&lt;/li&gt;&lt;li&gt;There's very little communication necessary between the main and render threads. Usually one SetTransform message for each graphics entity which has changed its position.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Communication is done with standard Nebula3 messages through a single message queue in the new GraphicsInterface singleton. This is an "interface singleton" which is visible from all threads. The render thread receives messages from the main thread (or other threads) and never actively sends messages to other threads (with one notable exception on the Windows platform: mouse and keyboard input).&lt;/li&gt;&lt;li&gt;Client-side code doesn't have to deal with creating and sending messages, because it talks through proxy objects with the render thread. Proxy objects provide a typical C++ interface and since there's a 1:1 relationship may cache data on the client-side to prevent a round-trip into the render thread (so there's some data duplication, but a lot less locking)&lt;/li&gt;&lt;li&gt;The Graphics subsystem offers the following public proxy classes at the moment:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Graphics::Display:&lt;/b&gt; setup and query display properties&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::GraphicsServer: &lt;/b&gt;creates and manages Stages and Views&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::Stage:&lt;/b&gt; a container for graphics entities&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::View: &lt;/b&gt;renders a "view" into a Stage into a RenderTarget&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::CameraEntity: &lt;/b&gt;defines a view volume&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::ModelEntity: &lt;/b&gt;a typical graphics object&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::GlobalLightEntity: &lt;/b&gt;a global, directional light source&lt;/li&gt;&lt;li&gt;&lt;b&gt;Graphics::SpotLightEntity:&lt;/b&gt; a local spot light&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;These proxy classes are just pretty interfaces and don't do much more then creating and sending messages into the GraphicsInterface singleton.&lt;/li&gt;&lt;li&gt;There are typically 3 types of messages sent into the render thread:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Synchronous messages which block the caller thread until they are processed, this is just for convenience and only exists for methods which are usually not called while the main game loop is running (like Display::GetAvailableDisplayModes())&lt;/li&gt;&lt;li&gt;Asynchronous messages which return immediately but pass a return-value back at some later time. These are non-blocking, but the result will only be available in the next graphics frame. The proxy classes do everything possible to hide this fact by either caching values on the client side, so that no communication is necessary at all, or by returning the previous value until the graphics thread gets around to process the message).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The best and most simple messages are those which don't require a return value. They are just send off by the client-side proxy and processed at some later time by the render thread. Fortunately, most messages sent during a frame are of this nature (e.g. updating entity transforms).&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;Creation of Graphics entities is an asynchronous operation, it is possible to manipulate the client-side proxy object immediately after creation even though the server-side entity doesn't exist yet. The proxy classes take care about all these details internally.&lt;/li&gt;&lt;li&gt;There is a single synchronization event per game-frame where the game thread waits for the graphics thread. This event is signalled by the graphics thread after it has processed pending messages for the current frame and before culling and rendering. This is necessary to prevent the game thread from running faster then the render thread and thus spamming its message queue. The game thread may run at a lower - but never at a higher - frame rate as the render thread.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Here's some example code from the testviewer application. It actually looks simpler then before since all the setup code has become much tighter:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt; &lt;span style="color:#0b5394;"&gt;       using namespace Graphics;&lt;br /&gt;       using namespace Resources;&lt;br /&gt;       using namespace Util;&lt;br /&gt;&lt;br /&gt;       &lt;span style="color:#274e13;"&gt;// setup the render thread&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt;&lt;span style="color:#0b5394;"&gt;        Ptr&amp;lt;GraphicsInterface&amp;gt; graphicsInterface = GraphicsInterface::Create();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt;&lt;span style="color:#0b5394;"&gt;        graphicsInterface-&amp;gt;Open();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt;&lt;span style="color:#0b5394;"&gt;       &lt;span style="color:#274e13;"&gt; // setup and open the display&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt;&lt;span style="color:#0b5394;"&gt;        Ptr&amp;lt;Display&amp;gt; display = Display::Create();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt;&lt;span style="color:#0b5394;"&gt;        // ... optionally change display settings here...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#0c343d;"&gt;&lt;span style="color:#0b5394;"&gt;        display-&amp;gt;Open();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="color:#073763;"&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;That's all that is necessary to open a default display and get the render thread up and running. The render thread will now happily run its own render loop.&lt;br /&gt;&lt;br /&gt;To actually have something rendered we need at least a Stage, a View, a camera, at least one light and a model:&lt;br /&gt;&lt;span style="color:#0b5394;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;        &lt;span style="color:#274e13;"&gt;// create a GraphicServer, Stage and a default View&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;        Ptr&amp;lt;GraphicsServer&amp;gt; graphicsServer = GraphicsServer::Create();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;        graphicsServer-&amp;gt;Open();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;        Attr::AttributeContainer dummyStageBuilderAttrs;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;        Ptr&amp;lt;Stage&amp;gt; stage = graphicsServer-&amp;gt;CreateStage(StringAtom("DefaultStage"), &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;&lt;br /&gt;                                                                           Graphics::SimpleStageBuilder::RTTI, &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;&lt;br /&gt;                                                                           dummyStageBuilderAttrs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;);&lt;br /&gt;&lt;br /&gt;       Ptr&amp;lt;View&amp;gt; view = this-&amp;gt;graphicsServer-&amp;gt;CreateView(InternalGraphics::InternalView::RTTI,&lt;br /&gt;                                                                              StringAtom("DefaultView"),&lt;br /&gt;                                                                              StringAtom("DefaultStage"),&lt;br /&gt;                                                                              ResourceId("DX9Default"),&lt;br /&gt;                                                                              true);&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#274e13;"&gt;        // create a camera and make it the active camera for our view&lt;br /&gt;       &lt;span style="color:#0b5394;"&gt;Ptr&amp;lt;CameraEntity&amp;gt; camera = CameraEntity::Create();&lt;br /&gt;       camera-&amp;gt;SetTransform(matrix44::translation(0.0f, 0.0f, 10.0f));&lt;br /&gt;       stage-&amp;gt;AttachEntity(camera.cast&amp;lt;GraphicsEntity&amp;gt;());&lt;br /&gt;       view-&amp;gt;SetCameraEntity(camera);&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#274e13;"&gt;        // create a global light source&lt;br /&gt;       &lt;span style="color:#0b5394;"&gt;Ptr&amp;lt;GlobalLightEntity&amp;gt; light = GlobalLightEntity::Create();&lt;br /&gt;       light-&amp;gt;SetTransform(matrix44::rotationx(n_deg2rad(-70.0f)));&lt;br /&gt;       stage-&amp;gt;AttachEntity(light.cast&amp;lt;GraphicsEntity&amp;gt;());&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#274e13;"&gt;        // finally create a visible model&lt;br /&gt;&lt;span style="color:#0b5394;"&gt;        Ptr&amp;lt;ModelEntity&amp;gt; model = ModelEntity::Create();&lt;br /&gt;       model-&amp;gt;SetResourceId(ResourceId("mdl:examples/eagle.n2"));&lt;br /&gt;       stage-&amp;gt;AttachEntity(model.cast&amp;lt;GraphicsEntity&amp;gt;());&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="color:#073763;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#0b5394;"&gt;&lt;span style="color:#000000;"&gt;That's the code to setup a simple graphics world in the asynchronous rendering case. There are a few issues I still want to fix (like the InternalGraphics::InternalView::RTTI thing). The only thing that's left is to add a call to GraphicsInterface::WaitForFrameEvent() somewhere into the game-loop before updating the game objects for the next frame. The classes App::RenderApplication and App::ViewerApplication in the Render layer will actually take care of most of this stuff.&lt;br /&gt;&lt;br /&gt;There's some brain-adaption required to work in an asynchronous rendering environment:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;there's always a delay of up to one graphics frame until a manipulation actually shows up on screen&lt;/li&gt;&lt;li&gt;it's hard (and inefficient) to get data back from the render thread&lt;br /&gt;&lt;/li&gt;&lt;li&gt;it's impossible for client-threads to read, modify and write-back data within one render-frame&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;For the tricky application specific stuff I'm planning to implement some sort of installable client-handlers. Client threads can install their own custom handler objects which would run completely in the render-thread context. This is IMHO the only sensible way to implement application specific graphics functionality which requires exact synchronization with the render-loop.&lt;br /&gt;&lt;br /&gt;I've had to do a few other changes to the existing code base for the asynchronous rendering to work: Mouse and keyboard events under Windows are produced by the application Windows (which is owned by the render thread), but the input subsystem lives in the game thread. Thus there needs to be a way for the render thread to communicate those input events into the main thread. I decided to derive a ThreadSafeDisplayEventHandler class (and ThreadSafeRenderEventHandler for the sake of completeness). Client threads can install those event handlers to be notified about display and render events coming out of the render-thread.&lt;br /&gt;&lt;br /&gt;The second, bigger, change affected the Http subsystem. Previously, HttpRequestHandlers had to live in the same thread as the HttpServer, which isn't very useful anymore now that important functionality has been moved out of the main thread. So I basically moved the whole Http subsystem into its own thread as well, and HttpRequestHandlers may now be attached from any thread. There's a nice side effect now that a Http request only stalls the thread of the HttpRequestHandler which processes the request.&lt;br /&gt;&lt;br /&gt;There's still more work to do:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;need to write some stress-tests to uncover any thread-synchronization bugs&lt;/li&gt;&lt;li&gt;need to do performance investigations and profiling (are there any unintended synchronizations issues?)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;thread-specific low-level optimization in the Memory subsystem as detailed in one of my previous posts&lt;/li&gt;&lt;li&gt;optimize the messaging system as much as possible (especially creation and dispatching)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I also want to implement some sort of method to run the rendering in the main thread, partly for debugging, partly for platforms with simple single-core CPUs&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Phew, that's all for today :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1217510401325801990?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1217510401325801990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1217510401325801990' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1217510401325801990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1217510401325801990'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/03/alright-application-layer-is-now.html' title='Nebula3&apos;s Multithreaded Rendering Architecture'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-838250886156805798</id><published>2008-02-28T17:00:00.007+01:00</published><updated>2008-02-28T17:28:51.568+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>COD4 FTW!</title><content type='html'>Hmm, &lt;a href="http://www.360voice.com/tag/FlohOfWoe"&gt;just noticed&lt;/a&gt; that COD4 is now my personal most-played game, replacing Oblivion which ruled at the top spot since I bought my 360 in 2006. The funny thing is that I remember Oblivion as that huge time-eater which I played the whole summer of 2006, while COD4 feels like I just barely started to really play it. Scary.&lt;br /&gt;&lt;br /&gt;I also finally finished the final boss in Prince Of Persia (the XBLA remake)! The combat system is surprisingly complex, attacking and blocking requires very good timing, a bit like the sword fights in Assassins Creed. Oh and I started with Lost Odyssey. Don't know what to think of it yet. It didn't exactly grab me, I'm 3 hours in or so, and there's just nothing happening in this game! Everything is so stretched out, and I keep thinking "man I could play some COD4 instead of struggling through this borefest"... and that's what I usually do about 10 minutes later...&lt;br /&gt;&lt;br /&gt;I'm also currently on my third DMC4 play-through in Son-Of-Sparda mode. Great great game. Nice distraction until the &lt;a href="http://www.xbox.com/en-US/games/n/ninjagaiden2/"&gt;king returns in June&lt;/a&gt; ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-838250886156805798?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/838250886156805798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=838250886156805798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/838250886156805798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/838250886156805798'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/02/cod4-ftw.html' title='COD4 FTW!'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7445121868839829891</id><published>2008-02-27T18:51:00.004+01:00</published><updated>2008-02-28T12:46:43.337+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Lowlevel Optimizations</title><content type='html'>I'm currently doing memory optimizations in Drakensang, and together with the new ideas from the asynchronous rendering code in N3 I'm going to do a few low-level optimizations in the memory subsystem over the next time in Nebula3. Here's what I'm planning to do:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Add a thread-safe flag to the Heap class, currently a heap is always thread-safe, but there will be quite a few cases now where it makes sense to not have the additional thread-safety-overhead in the allocation routines.&lt;/li&gt;&lt;li&gt;Add some useful higher-level allocators:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;FixedSizeAllocator: This optimizes the allocation of many small same-size objects from the heap, it will pre-allocate big pages, and manage the memory within the pages itself. The main-advantage comes from the fact that all blocks in the page are guaranteed to be the same size.&lt;/li&gt;&lt;li&gt;BucketAllocator: This is a general allocator which holds a number of buckets for e.g. 16, 32, 48, ...256 byte blocks (the buckets are just normal FixedSizeAllocators). Small allocations can be satisified from the buckets, larger allocation go directly through the heap as usual.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Overwrite the new-operator in all RefCounted-derived classes to use the a BucketAllocator (however, I'll actually do some profiling whether this is actually faster then Windows' Low Fragmentation Heaps). This stuff will be behind the scenes in the DeclareClass()/ImplementClass()-macros, so there are no changes necessary to the class source code.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The biggest new feature (which depends on all of the above) is that I want to split RefCounted classes into thread-safe and thread-local classes. The idea is that a thread-local class promises that creation, manipulation and destruction of its objects happens from the same thread. A thread-local class can do a few important things with less overhead:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;thread-local classes would create their instances from a thread-local BucketAllocator which doesn't have to be thread-safe&lt;/li&gt;&lt;li&gt;thread-local classes could use normal increment and decrement operations for their refcounting instead of Interlocked::Increment() and Interlocked::Decrement(). Since every Ptr&lt;&gt; assignment changes the refcount of an object this may add up quite a bit.&lt;/li&gt;&lt;/ul&gt;By far most classes in Nebula3 can be thread-local, only message objects which are used for thread-communication, and some low-level classes need to be thread-safe. I'm planning to enforce thread-locallity in Debug mode by storing a pointer to the local thread-name in each instance, and checking in AddRef, Release and other RefCounted methods whether the current thread-context is the same (that's a simple pointer-comparision, and it happens only in Debug mode).&lt;br /&gt;&lt;br /&gt;The general strategy is to get away as far as possible from the general Alloc()/Free() calls, and to make memory management more "context sensitive" and also more static (in the sense that the memory layout doesn't change wildly over the runtime of the game). It's extremely important for a game application to set aside fixed amounts of memory right from the beginning of the project (and to let the game fail hard if the limits are violated), otherwise everything will grow without control, and towards the end of the project much time must be invested to cut everything back to reasonable limits.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7445121868839829891?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7445121868839829891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7445121868839829891' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7445121868839829891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7445121868839829891'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/02/lowlevel-optimizations.html' title='Lowlevel Optimizations'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-6148589292875619301</id><published>2008-02-19T18:30:00.003+01:00</published><updated>2008-02-19T19:13:56.830+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Nebula3 Februar 2008 SDK</title><content type='html'>Alright, here it is finally:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.radonlabs.de/internal/N3SDK_Feb2008.exe"&gt;N3SDK_Feb2008.exe&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Notable new features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a "quick'n'dirty port" of our current Nebula2 modular character and animation system&lt;br /&gt;&lt;/li&gt;&lt;li&gt;PSSM-VSM shadow support for global light sources (which I'm not quite happy with yet)&lt;/li&gt;&lt;li&gt;some restructuring and cleanup in the Application layer&lt;/li&gt;&lt;/ul&gt;The internal Wii port is coming along nicely, Johannes got SQLite up and running on the Wii (which will also be helpful for other console ports), and apart from physics and collision detection, the Application Layer is now running on the Wii.&lt;br /&gt;&lt;br /&gt;During the last 2 weekends I started to implement a new AsyncGraphics subsystem, which will put the Graphics subsystem and everything beneath it under its own thread. I'll write more about this in another post soon.&lt;br /&gt;&lt;br /&gt;Finally here's a new screenshot of the new "demo character":&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_cWdorEDEaNg/R7saR6MpcPI/AAAAAAAAAFA/oW31Xr7dtgE/s1600-h/n3feb2008.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_cWdorEDEaNg/R7saR6MpcPI/AAAAAAAAAFA/oW31Xr7dtgE/s400/n3feb2008.png" alt="" id="BLOGGER_PHOTO_ID_5168753892320178418" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-6148589292875619301?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/6148589292875619301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=6148589292875619301' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6148589292875619301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/6148589292875619301'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/02/nebula3-februar-2008-sdk.html' title='Nebula3 Februar 2008 SDK'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_cWdorEDEaNg/R7saR6MpcPI/AAAAAAAAAFA/oW31Xr7dtgE/s72-c/n3feb2008.png' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1318114611199246046</id><published>2008-02-09T20:27:00.000+01:00</published><updated>2008-02-09T20:28:18.193+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>COD4 Multiplayer</title><content type='html'>I have developed a serious addiction to COD4 multiplayer. Usually I'm not that big into competitive multiplayer, but I'm having my phases. Back in the old days, it was Counter Strike, a few years later I was excessively playing Battlefield2, and now for the last couple of weeks I'm totally hooked to COD4. On a console. With a game-pad. I tried the competitive multiplayer portions of Gears Of War, Rainbow Six Vegas and Halo3 before, and none of them really ticked with me in multiplayer like the old-school PC shooters. But COD4... one match did it. The reason - I think - is because COD4 is the love-child of CS and BF2, my two favorits of the past. Sessions feel very fast-paced, with an initial rush to the control-points, just like in CS. The class system and up-leveling is more like BF2, but it's more back-to-the-roots, especially the class system, which doesn't feature advanced classes like medics or engineers, instead, all classes are strictly offensive. Every single feature is extremely polished, and everything which would hinder the flow and speed of the game has been removed. And my personal killer-feature: you don't have to communicate a lot. Nothing breaks the immersion more then some jerks talking about some completely unrelated shit like their last GameStop-visit during a Team Deathmatch in some destroyed middle-eastern city. Fortunately the game plays just as well without headset. Big win.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1318114611199246046?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1318114611199246046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1318114611199246046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1318114611199246046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1318114611199246046'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/02/i-have-developed-serious-addiction-to.html' title='COD4 Multiplayer'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-5169553288718833213</id><published>2008-02-02T17:49:00.000+01:00</published><updated>2008-02-02T17:54:11.363+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>D3D Debugging</title><content type='html'>I just spent a bit of time debugging the D3D9 specific code. Running the test viewer under the D3D debug runtime and with the warning level to highest reveals 2 warnings:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;redundant render state switches (which I'm ignoring for now, the frame shader system already helps to reduce redundant state switches a lot, and fixing the remaining state switch warnings would involve implementing a D3DXEffectStateManager, but before I do this I want to make sure that my own redundant state switch detection would actually be faster then D3D's)&lt;/li&gt;&lt;li&gt;more serious is the second warning: "render target was detected as bound, but couldn't detect if texture was actually used in rendering". This is only a real problem if you want to read from the same render target you're currently rendering to, which isn't happening anywhere in Nebula3 (unless you screw up the frame-shaders). I fixed the warning by adding a "UnbindD3D9Resources()" method to the D3D9RenderDevice, which is called at the end of a rendering pass, and before the D3D9 device is shut down. The method simply sets the texture stages, vertex buffer and index buffer of the device to NULL.&lt;/li&gt;&lt;/ul&gt;The most serious problem though was that Direct3D reported memory leaks when shutting down the application. Finding a D3D9 memory leak can be tricky, but thankfully Direct3D has a nice mechanism built into its debug runtime to find the allocation which causes the memory leak: on shutdown D3D writes a memleak log to debug-out, where each memory leak is given an unique id. The problem is, that even one forgotten Release() call can generate hundreds of memory leaks because of D3D's many internal dependencies. The most interesting leak however is usually the last reported, at the bottom of the leak-report. To find the offending allocation, open the DirectX Control Panel, go to the Direct3D 9 tab, and enter the last reported AllocID into the "Break On AllocID" field. Run the application in the debugger, and it should break at the allocation call in question. Turns out I forgot 3 Release() calls: one in D3D9RenderTarget::BeginPass() after obtaining the backbuffer surface from the D3D9 device, one in D3D9RenderTarget::EndPass() after a GetSurfaceLevel(), and after another GetSurfaceLevel() call in D3D9RenderDevice::SaveScreenShot().&lt;br /&gt;&lt;br /&gt;The moral of the story: read the D3D9 docs carefully even for "uninteresting" functions, and run the application through the debug runtime after each change to the rendering code, to prevent such bugs from piling up to unmanageable levels.&lt;br /&gt;&lt;br /&gt;I wanted to get this stuff fixed before the January SDK release, so this will come next week as time permits. Drakensang bugfixing and optimization has full priority for me at the moment.&lt;br /&gt;&lt;br /&gt;Completely unrelated:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Watched Death Proof yesterday, and I was a little bit disappointed. The first half was outright boring, then 10 seconds with (probably) the most spectacular (and gory) car crash in movie history. The second half with the "new girls" was actually really good, but the car-chase at the end and the finale was quite a letdown as well, guess I was hoping to see Kurt Russel die in a more spectacular way hehe...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;RezHD on XBLA is ... wow.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-5169553288718833213?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/5169553288718833213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=5169553288718833213' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5169553288718833213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/5169553288718833213'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/02/i-just-spent-bit-of-time-debugging-d3d9.html' title='D3D Debugging'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-8480901136339770368</id><published>2008-01-17T18:50:00.000+01:00</published><updated>2008-01-17T18:54:54.339+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>First Render: Wii</title><content type='html'>Here's the first screenshot from the Nebula3 Wii port. There are still some rendering artefacts which we're looking into, but technically it's the first rendering which is fully running through the Nebula3 rendering pipeline on the Wii :)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_cWdorEDEaNg/R4-V-ghplzI/AAAAAAAAAE4/lqPm8BHINGk/s1600-h/wii_tiger.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_cWdorEDEaNg/R4-V-ghplzI/AAAAAAAAAE4/lqPm8BHINGk/s400/wii_tiger.jpg" alt="" id="BLOGGER_PHOTO_ID_5156504999478007602" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-8480901136339770368?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/8480901136339770368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=8480901136339770368' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8480901136339770368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8480901136339770368'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/01/first-render-wii.html' title='First Render: Wii'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_cWdorEDEaNg/R4-V-ghplzI/AAAAAAAAAE4/lqPm8BHINGk/s72-c/wii_tiger.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9008562714150847692</id><published>2008-01-06T16:15:00.000+01:00</published><updated>2008-01-06T16:17:08.875+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Happy New Year</title><content type='html'>The January 2008 SDK release is well on track. I think we'll have to settle for a bimonthly release cycle in the future. While the main chunk of work has gone into the Wii-port (which isn't part of the public SDK release of course) there are still two nice new features for the Win32 version:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;our modular character system (direct port from Nebula2), so the next testgame.exe application will have proper characters instead of a placeholder geometry&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="PSSM" href="http://appsrv.cse.cuhk.edu.hk/%7Efzhang/pssm_vrcia" id="bq87"&gt;PSSM&lt;/a&gt; shadow support for global light sources&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I feel that PSSM (Parallel-Split-Shadow-Maps) combined with VSM (Variance Shadow Mapping) currently gives the best bang-for-the-buck in terms of quality vs. performance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9008562714150847692?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9008562714150847692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9008562714150847692' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9008562714150847692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9008562714150847692'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2008/01/january-2008-sdk-release-is-well-on.html' title='Happy New Year'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3355049516463960868</id><published>2007-12-16T23:09:00.000+01:00</published><updated>2007-12-16T23:58:25.679+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Assassin's Creed Wrap Up</title><content type='html'>I finally reserved a few hours to finish up on Assassin's Creed. Yawn... all this cheap pseudo-science crap was really getting on my nerves towards the end. It seems that every stupid conspiracy theory ever invented has been stuffed into AC's "story".&lt;br /&gt;&lt;br /&gt;The game itself was actually quite a chore during the last few hours, because nothing really unexpected or new happened (yes, the game tries to have some sort of a surprise ending, but one can see this coming from a mile away). For the little variety the game-play offers, the game just feels too long IMHO. Everything is just too stretched-out. Overall it's a pretty good game, but now that it's over I feel somewhat ... unsatisfied. The fact that the game doesn't seem to have a real ending doesn't help either. Yes, I discovered the credits ... but what the hell now?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3355049516463960868?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3355049516463960868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3355049516463960868' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3355049516463960868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3355049516463960868'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/12/assassins-creed-wrap-up.html' title='Assassin&apos;s Creed Wrap Up'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9022272483933488973</id><published>2007-12-04T15:09:00.000+01:00</published><updated>2007-12-04T15:10:38.394+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Mass Effect</title><content type='html'>Holy shit, Mass Effect is f*cking &lt;b&gt;E-P-I-C&lt;/b&gt;. The "acting" and story-telling is better then in any Star Wars movie, game-play is (surprisingly) very Deus Ex'ish. The last 2 or 3 hours are simply breathtaking (I clocked in at about 36 hours with most of the side quests). Mass Effect is simply one of the best games ever made. There are some technical glitches (most notable and annoying is the extreme texture popup, especially after loading a saved game and at the beginning of some cutscenes... only low-detail textures are displayed while the high-detail textures are streamed in, sometimes it takes several seconds until everything looks right). There's also some stuttering during game play (most likely also loading related). The graphics quality is a mixed bag, some of the less important NPCs look very bad compared to the extremely detailed and convincing main characters, most of the environment graphics looks last-gen, interestingly one of them (Ilos) looks extremely good, almost like it has been done by a different team, or the designers had a lot more time reserved for this one location. But all in all these are just very tiny flaws and don't stop the game from being an absolute masterpiece.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9022272483933488973?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9022272483933488973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9022272483933488973' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9022272483933488973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9022272483933488973'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/12/holy-shit-mass-effect-is-fcking-e-p-i-c.html' title='Mass Effect'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-162425725979054180</id><published>2007-11-17T14:12:00.000+01:00</published><updated>2007-11-17T14:27:34.911+01:00</updated><title type='text'>AC's Political Correctness BS</title><content type='html'>  Assassins Creed displays something along the lines of "this product is a work of fiction and has been produced by a multiethnical team of various religious beliefs" when it starts up. This is the most hilarious/concerning quote I have ever seen in a video game. They should have written instead "we are a scared bunch of spineless pussies who are afraid that our studios are blown up by christian and/or muslim fundamentalists". What's coming next, a disclaimer in a World War 2 game, that members of various - uh - political beliefs have worked on the team just to appease the nazis and communists? The end is near I say.&lt;br&gt; &lt;br&gt; The game is much more controversial where it probably didn't intend to be: game-design and game-play. There are many things I absolutely love, and one or two things I absolutely hate. I haven't played through yet, so I'm not qualified to write a "proper review", but I think I can already say that it is definitely a must-have game. It does many things different then the mainstream, and that's already enough reason to buy the game, even if it tries sometimes to be too innovative and too avant-garde which may put off some players. We'll have to see how it does commercially. I hope it does well to demonstrate to publishers that innovation may actually pay off. As a gamer I'm usually more conservative though, a game should do at most one or two completely new things, and use established mechanics and even clichés for all the other elements in the game, otherwise I'm not really feeling comfy and at home, especially in the beginning of a game. On the other hand, some games have to be the forerunners and crash-test-dummies for new game-play mechanics. Otherwise we'd still be stuck with Pong.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-162425725979054180?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/162425725979054180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=162425725979054180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/162425725979054180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/162425725979054180'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/11/assassins-creed-displays-something.html' title='AC&apos;s Political Correctness BS'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-607798933768875950</id><published>2007-11-15T18:23:00.000+01:00</published><updated>2007-11-15T18:24:34.062+01:00</updated><title type='text'>Nebula3 November SDK</title><content type='html'>Alright, here's the new Nebula3 SDK: &lt;a href="http://www.radonlabs.de/internal/n3sdk_nov2007.exe" id="qtug" title="http://www.radonlabs.de/internal/n3sdk_nov2007.exe"&gt;http://www.radonlabs.de/internal/n3sdk_nov2007.exe&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Some notable new features:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;first version of the Application Layer plus a small sample app&lt;/li&gt;&lt;li&gt;now also works on ATI cards which support shader model 3.0 (X-above-1000)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;a new global light source type&lt;/li&gt;&lt;li&gt;resources now loaded from zip archive&lt;br /&gt;&lt;/li&gt;&lt;li&gt;many bugfixes&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;There are a quite few known issues in this release:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;some (new) VSM-related visual artefacts in the shadow system (light leaking and shadow grain near some shadow casters), this must be fixed by tuning some VSM parameters which I didn't quite have the time to do right&lt;/li&gt;&lt;li&gt;new Application Layer sample app has clumsy controls and camera&lt;br /&gt;&lt;/li&gt;&lt;li&gt;shadows are not rendered when shadow caster is not visible which leads to shadow pop-up in the App Layer sample application&lt;br /&gt;&lt;/li&gt;&lt;li&gt;re-building assets requires the Nebula2 Toolkit For Maya&lt;/li&gt;&lt;li&gt;some new Doxygen docs pages are messy&lt;/li&gt;&lt;li&gt;ODE, OPCODE and GIMPACT not credited yet in the docs&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So this release is a bit rough, I hope the next one will be more polished. But I really wanted to push it out the door instead of spending even more time to fix stuff.&lt;br /&gt;&lt;br /&gt;Here are a few screenshots:&lt;br /&gt;&lt;div id="f:wa" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 640px; height: 480px;" src="http://docs.google.com/File?id=dd795pnb_22gsbw4wcx" /&gt;&lt;/div&gt;This is the testviewer.exe with one global light (cannot cast shadows yet, I'm planning to implement &lt;a title="Parallel-Split Shadow Maps" href="http://appsrv.cse.cuhk.edu.hk/%7Efzhang/pssm_vrcia/" id="f_:5"&gt;Parallel-Split Shadow Maps&lt;/a&gt; for global light sources), plus 2 spot lights which cast VSM shadows.&lt;br /&gt;&lt;br /&gt;The next one is a screenshot of the new testgame.exe sample application, with a player-controllable avatar and some physics boxes to play around with:&lt;br /&gt;&lt;br /&gt;&lt;div id="hu7y" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 640px; height: 480px;" src="http://docs.google.com/File?id=dd795pnb_23gprhrhgh" /&gt;&lt;/div&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;-Floh.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-607798933768875950?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/607798933768875950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=607798933768875950' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/607798933768875950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/607798933768875950'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/11/alright-heres-new-nebula3-sdk-httpwww.html' title='Nebula3 November SDK'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7305841428261097021</id><published>2007-11-12T16:00:00.000+01:00</published><updated>2007-11-12T16:01:58.558+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>COD4</title><content type='html'>&lt;b&gt;  Call Of Duty 4&lt;/b&gt; rocks in every aspect. No point in babbling about it here, you really have to see for yourself. If you only play one FPS this year, make it COD4. If the game would have a R6-Vegas-style cover system, it would reach critical mass and collapse into a singularity of pure gaming perfection, thus destroying earth and human civilization. Maybe that's why they left it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7305841428261097021?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7305841428261097021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7305841428261097021' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7305841428261097021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7305841428261097021'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/11/call-of-duty-4-rocks-in-every-aspect.html' title='COD4'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2969841205249805334</id><published>2007-11-04T15:29:00.000+01:00</published><updated>2007-11-04T15:31:27.436+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Shadow Fixes</title><content type='html'>Phew, I think I have fixed most of the pressing problems in the VSM code. I didn't manage to get the number of executed instructions in the pixel shader down to a reasonable number with dynamic branching as I was hoping. So I went the shader-library way and added shader variations for 1 local light, 2 local lights, etc... up to 8 local lights, so that performance with a low number of dynamic lights has become dramatically better especially on graphics cards with low fillrate (shader optimizations aren't a big priority yet however). Shader model 3.0 still has some annoying restrictions when trying to do a single-pass/multiple-light shader, so the übershader approach isn't very practical in the end. Hmpfh. I'm almost starting to consider deferred lighting... at least as a second option. Shadow quality has been improved a little bit because some bugs in the 2x2 downsample and gaussian blur filters have been fixed, finally I'm now emulating bilinear filtering when sampling the shadow buffer in the pixel shader so that shadow borders should now be properly smoothed also on cards which don't support bilinear filtering of G16R16F texture formats (like ATI's).&lt;br /&gt;&lt;br /&gt;I'll try to get a new SDK out of the door next week, it's a little more complicated to coordinate a release now that 3 people are actively working on N3.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2969841205249805334?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2969841205249805334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2969841205249805334' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2969841205249805334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2969841205249805334'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/11/phew-i-think-i-have-fixed-most-of.html' title='Shadow Fixes'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-9126243636133246059</id><published>2007-11-04T12:37:00.000+01:00</published><updated>2007-11-04T12:38:35.570+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Bored To Death</title><content type='html'>Alright, I think I've had it with JRPGs. Eternal Sonata came out 2 weeks before in Germany. I've enjoyed the demo quite a bit actually so I gave it a try. The graphics are very, very pretty, and technically the game is very solid. But: story and gameplay ... oh where to begin... what the fuck is up with the cutscenes? Very pleasing to the eye but even the cheapest, most shittiest German telenovela is more entertaining. On the one hand, everything is so extremely childish that if I would be a 10-year old boy I would be completely embarrassed to watch this shit. On the other hand it's about heavy stuff like drug abuse, terminal illness, revolution and war. WTF? And they are tooo loooong. I swear it took 15 or 20 minutes of completely useless chatter until the game actually started. Well at least it's possible to skip the cutscenes... which brings us to the second problem: gameplay. This game is so extremely linear that watching a DVD offers about the same set of choices. You can pause, rewind, or go forward. There is almost no sense of exploration, no choices in customization (everything is just linearly upgraded), shops are pretty much useless, they basically just offer to buy some piece of equipment which you may have missed in the previous area during exploration (and it's nearly impossible to miss something because every treasure chest is right near The Way). Combat is actually quite fun because it's more action oriented compared to the traditional purely turn based battle, but it's too repetitive to keep me interested in the long run (yes, my attention span has suffered a lot since I switched to console gaming). Eternal Sonata has a very pretty, expensive looking shell, but unfortunately it seems to be completely hollow inside. &lt;br&gt;&lt;br&gt;On to something completely different: &lt;b&gt;Naruto&lt;/b&gt;! I never heard the name in another context. Guess it's some anime that's currently running in the USA, maybe here in Germany too on some obscure TV channel. I've seen the pretty screenshots, read some good things about the game, so I bought it in favour of the Orange Box which came out last week as well (Portal will have to wait a little bit I guess). And the game doesn't disappoint at all. The graphics are really impressive: stylish, great, consistent art direction and a lot of attention to little details. I've spent quite some time just running around in the world and looking at all the pretty scenery. Gameplay is a shameless mixture of GTA and Tekken with a very little bit of JRPG.... aaalriiiight, let me explain: The GTA aspect is there because the village where the game takes place is basically your sandbox where you can run around and solve small quests and do errands for the villagers. At the start of the game everybody hates you because you're that small annoying little brat who wants to be a ninja. By helping the villagers with their problems, more and more of them start to like you, which is good because villagers that like you can give you directions in future quests. The JRPG aspect is there because combat doesn't take place in the game world, but as you encounter an enemy, the actual fighting will happen in a small fighting arena just as in a typical JRPG (thankfully that's where the similarity to JRPGs ends). The combat is just like in an arcade fighter with simple combos, blocking, throws and special attacks. The special attacks are especially funny, because they are accompanied by absurd and completely overdone anime effects &lt;b&gt;SHADOW-CLONE-JUTSU!!! Blam-Blam-Splat-Wooosh!!!&lt;/b&gt; You get the general idea :) They even managed to sneak Quick Timer Events into the game in a way that isn't annoying, which earns an extra point because usually I hate QTEs. The story is told through traditional 2D anime clips which look like they're taken directly from the original TV series and is - well... mildly entertaining to me, but probably a big deal for fans of the original series.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-9126243636133246059?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/9126243636133246059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=9126243636133246059' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9126243636133246059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/9126243636133246059'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/11/alright-i-think-ive-had-it-with-jrpgs.html' title='Bored To Death'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7156829765239694071</id><published>2007-11-03T21:24:00.000+01:00</published><updated>2007-11-03T22:37:01.002+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>The Nebula3 Application Layer</title><content type='html'>      Nebula3's Application Layer provides a standardized high-level game framework for application programmers. It's the next version of Mangalore (Nebula2's application framework) integrated into Nebula3. N3's Application Layer is the result of years of refactoring (one could say that this started with our very first big project "Urban Assault" 10 years ago). Mangalore has now reached a rather stable state, where no "big" design changes are intended in the foreseeable future. Thus programmers familiar with Mangalore will immediately find their way around in the Nebula3 Application Layer. &lt;br&gt;&lt;br&gt;Mangalore had officially been started in 2003 when we learned the hard way that it is critical for an independent developer to work on several titles for several publishers at once to spread out the risks (German publishers have the unfortunate tendency to go nearly bankrupt quite frequently). So one very important design goal for Mangalore was to provide a common game application framework for a company where several teams work on game-projects of different game genres, and most importantly, a game-framework which enables us to do small - yet complete - games in a very short time-frame (our canonical "most minimal project" has a 3 month production-time-frame, and a team size of 5 people full-time (2 programmers, 2 graphics guys, 1 level designer), plus a half or third of a project manager). To make a long story short: building several "small projects" in parallel is many times harder then doing one "big project" because there are many parts of a game-project which simply don't scale down with the overall project size. On the content side, our strictly standardized asset pipeline in the form of our toolkit was the precondition for our multi-project strategy because it enabled us to switch modelers and animators between projects with practically no overhead (for instance it is not uncommon to build all graphical assets for a small project in only a few weeks, to directly share character animations between projects, or to have key people (like for instance character animators) help out in another project for a few days). &lt;br&gt;&lt;br&gt;Mangalore (and now the N3 Application Layer) basically tries to solve the same problems in the programming domain, to enable our application programmers to start a new project with very small setup-overhead, and to help implement its game-play features on-time and on-budget. The following bullet points are probably the most important Mangalore features:&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;provide a fully functional generic "skeleton application" so that something is visible on the screen from Day One of the project&lt;/li&gt;&lt;li&gt;integrates with our standardized level-design and modeling work-flows, and thus provides a common "social interface", mindset and vocabulary between our programmers, modelers/animators and level-design guys&lt;/li&gt;&lt;li&gt;has very few, very strictly defined concepts how an application should implement its game-specific code (it's relatively easy for a Mangalore programmer to decide the "where" and "how" questions when faced with the implementation of a new game feature)&lt;br&gt;&lt;/li&gt;&lt;li&gt;it's modular enough to enable a team of programmers to work on the game-logic without stepping on the other programmers' feet too much&lt;/li&gt;&lt;li&gt;"New Game", "Continue Game", "Load Game" and "Save Game" are standardized features (that's an important one: Load/Save works right from the beginning, and mostly without requiring the programmer to write a single line of load/save-related code)&lt;br&gt;&lt;/li&gt;&lt;li&gt;provide a growing set of reusable modules for future projects (we formalized this a bit more in the N3 Application Layer compared to Mangalore by introducing so called "GameFeatures")&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;The Application Layer is built around the following basic concepts:&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Entity:&lt;/b&gt; a game object, container for Properties and Attributes, manipulated through Messages&lt;br&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Property: &lt;/b&gt;implement per-entity aspects of game-logic&lt;br&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Manager: &lt;/b&gt;implements global aspects of game-logic&lt;/li&gt;&lt;li&gt;&lt;b&gt;Attribute: &lt;/b&gt;key/value pairs representing the persistent state of an Entity&lt;br&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Message:&lt;/b&gt; used for communication between entities&lt;br&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;GameFeature: &lt;/b&gt;groups Properties, Managers, Messages and Attributes by functionality&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;An &lt;b&gt;Entity&lt;/b&gt; represents a single game object, like an enemy space-ship, the player avatar, or a treasure-chest. An important aspect of the Application Layer is that the class Game::Entity is not sub-classed to add functionality, instead Attributes and Properties define the actual game functionality of the entity. We learned very early that representing game objects through a class hierarchy in a complex game project brings all types of problems, where spaghetti-inheritance, fat base classes and redundant code are just the obvious ones (let's say you do a traditional realtime strategy game with vehicle units, so you create a Vehicle class, and derive a GroundVehicle and an AirVehicle class, which can implement navigation on the ground and in the air respectively, but now you want to add combat functionality, hmm... create a CombatGroundVehicle class, and a CombatAirVehicle class? Or would it be better to create a CombatVehicle class and derive GroundCombatVehicle and AirCombatVehicle? But wait, some of the vehicles should gather resources instead of fighting... you get the general idea, I think every game programmer faces this problem very early in his career).&lt;br&gt;&lt;br&gt;That's where &lt;b&gt;Properties&lt;/b&gt; come into play. A property is a small C++ object which is attached to an Entity object and which adds a specific piece of functionality to that entity. For instance, if a specific entity type should be able to render itself, a &lt;b&gt;GraphicsProperty&lt;/b&gt; is attached, if it should be able to passively bounce and roll around in the game world, a &lt;b&gt;PhysicsProperty&lt;/b&gt; is required, if an entity should be able to control the camera, a &lt;b&gt;CameraProperty&lt;/b&gt; is added, and so on. Or for the above strategy game, a &lt;b&gt;GroundMovementProperty&lt;/b&gt;, &lt;b&gt;AirMovementProperty&lt;/b&gt;, &lt;b&gt;CombatProperty &lt;/b&gt;and a &lt;b&gt;GatheringProperty &lt;/b&gt;would be required, which are combined to create the functionality of the different unit types. Ideally, Properties are as autonomous and independent of each other as possible, so that they can be combined without restrictions (in a real world project, some Properties will always depend on each other, but experience has shown that the resulting usage restrictions are mostly acceptable). Properties pretty much solve the inheritance-problems outlined above. A new entity type is not implemented by subclassing from the Game::Entity class, instead new entity types are defined by combining several specialized properties.&lt;br&gt;&lt;br&gt;The next problem we need to solve is the interface and communication problem. Properties need to communicate with each other (either with Properties attached to the same Entity, or with Properties attached to other Entities). Calling C++ methods on other Properties would ultimately introduce a lot of dependencies between Property classes which we want to avoid because this would very soon result in the same set of restrictions we just solved by fixing the Entity-class-inheritance-problem with Properties. Virtual methods would help a little bit because it would limit the dependencies on a few base classes, but this would just move the inheritance problem from entities to properties. &lt;b&gt;Messages&lt;/b&gt; are used to solve this dilemma. Think of a Message as the next abstraction level of a virtual method call. While a virtual method call requires that the caller knows a target object and a base C++ interface, a Message just requires the caller to know the target object in the form of an Entity but no specific interface. The Entity will route the Message to interested Properties which will ultimately process the Message. The caller usually doesn't know which Property processes a Message, or whether the Message is even processed at all. &lt;br&gt;&lt;br&gt;A C# programmer would now raise his arm and remark that this is exactly what Interfaces, Delegates and Events are for. And of course he's completely right. Alas, we're working in old-school C++. There is however more room for optimization in the Application Layer in the future (for instance, Message dispatching could be optimized by implementing a delegate-like mechanism).&lt;br&gt;&lt;br&gt;&lt;b&gt;Attributes&lt;/b&gt; are typed key/value pairs attached to entities. Each entity has a well-defined set of attributes which completely represents the persistent state of the entity. Attributes are used to describe the initial state of an entity, and to save and load the state of an Entity using the standard Load/Save mechanism of the Application Layer. Usually, a specific property is responsible for a subset of the entity's attributes. As a general rule, a specific attribute should only be manipulated by one property, but may be read by everyone.&lt;br&gt;&lt;br&gt;Many features of a game-application don't fit into entities and are better implemented in some central place (the overall code design of some of our early projects suffered a lot from failing to understand that NOT EVERYTHING is an entity). For instance handling input or controlling the camera in one central place is sometimes (often?) better then spreading the same functionality over several Property classes, which then may need to spend a lot of effort to synchronize and communicate with other properties). Those global aspects of game-logic are put into subclasses of &lt;b&gt;Manager&lt;/b&gt;. Managers are typical Singleton objects and usually provide services which need to be available "everywhere" in the game code.&lt;br&gt;&lt;br&gt;Finally, a &lt;b&gt;GameFeature&lt;/b&gt; is a new concept which didn't exist in Mangalore. A GameFeature is more or less just a nifty name for a bunch of source files which compile into a static link library consisting of related Properties, Managers, Messages and Attributes (all of them optional). GameFeatures are mainly an infrastructure to encourage and standardize code reuse between projects. The idea is that at the beginning of a project the lead programmer starts by picking and choosing from the existing set of GameFeatures those which suit his project, and (ideally) to group new functionality into new GameFeatures which may be of use for later projects. The Application Layer comes with a small number of standard GameFeatures, enough to implement a generic 3D application with a player-controllable avatar, chase camera and passive physics for environment objects, but it's really intended for more complex stuff, like a dialog system, a generic inventory system, or lets say, the guts of a typical "horse riding game" ;)&lt;br&gt;&lt;br&gt;The Application Layer isn't perfect and doesn't solve all problems of course. For instance it may be difficult to decide whether a piece of functionality should better go into Properties or into a Manager. Also, a typical problem we are frequently facing is that functionality is split into too many, too small parts which results in too many, too fine-grained Property classes, which in turn requires too much communication between those properties.  So a project *still* needs an experienced and pragmatic lead programmer which lays down the basic infrastructure of the code at the beginning of the project.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7156829765239694071?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7156829765239694071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7156829765239694071' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7156829765239694071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7156829765239694071'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/11/nebula3s-application-layer-provides.html' title='The Nebula3 Application Layer'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-3515572133185597187</id><published>2007-10-25T18:54:00.000+01:00</published><updated>2007-10-25T19:15:07.323+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Status Update</title><content type='html'>Quick update:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A couple of new Wii and DS devkits have arrived this week, one of the Wii-kits is for me so I will join the party soon, at least part-time.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I'm very busy working on Drakensang at the moment, so there won't be a lot of new stuff in the next Nebula3 release from my side, after all I fixed quite a few bugs in the zip-archive code, so that all runtime data is now loaded by default from an export.zip archive (it's also working on the Xbox360, but I will add support for the 360's native compressor at some later time because it's most likely faster then the generic zlib).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Johannes Kosanetzky pretty much finished up the Application layer by porting the essential parts of Mangalore over to Nebula3, this will be in the next SDK release even if it's still work in progress. The general plan here is to have a nice little demo application with simple physics, a player-controllable avatar and a chase camera. All with complete integration into our existing level design workflow.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Malte has been working on porting the Foundation layer over to the Wii, and is now almost finished with it. The Wii specific code won't be part of the public SDK of course.&lt;/li&gt;&lt;li&gt;The Wii-port got a priority boost recently. Because of this we will essentially take a shortcut and add a new "Nebula2 backward compatibility" layer. This layer will contain essential Nebula2 subsystems (for instance animation, audio, characters, etc...) which are just brought over to N3 without alot of refactoring, so that we can get a good base for a real-world project ASAP. The plan is to replace those N2-subsystem step-by-step with properly refactored systems in parallel to actual project development, so that we have enough time for proper refactoring and to implement platform-specific optimizations where applicable.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Slight Wii rant: Aaargh... hardware considerations aside (involving GameCubes, duct tape, etc... which I have no problem with since a scalable engine can take care of that). But I'm really shocked about the development environment and API. I think the last time I worked in a similar environment was when we did Urban Assault in Watcom-C under DOS-Protected-Mode. This was in the mid-90's. Memories of AmigaOS pop up as well (although AmigaOS was in several aspects more advanced, and this was in the mid-80's). I appreciate the simplicity of the hardware and software and all, but... WTF? It's like 20 years of progress in software development simply didn't happen. We're basically expected to built gothic cathedrals with a hand-axe... did I mention already how amazingly f*cking cool the 360's development environment is? Well nevermind...&lt;br /&gt;&lt;br /&gt;One more reason to get N3 up and running on the Wii ASAP ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-3515572133185597187?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/3515572133185597187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=3515572133185597187' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3515572133185597187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/3515572133185597187'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/10/quick-update-couple-of-new-wii-and-ds.html' title='Status Update'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7336353187193361451</id><published>2007-10-20T14:21:00.000+01:00</published><updated>2007-10-20T15:00:51.547+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Game Development Essentials'/><title type='text'>Level Design And Build System Thoughts</title><content type='html'>      I've been discussing with Bernd a lot lately how we could improve our build system and level design process over the next months. Turnaround times for complete and incremental builds, and also the "local turnaround" of level designers are starting to become critical for a "big" project like Drakensang. A complete (nightly) build is now at around 11 hours (this includes recompiling and rebuilding everything, building an installer and uploading the result to an FTP site). An incremental build (during the day) takes at least half an hour and up to 2 hours (without building the installer and uploading). To put this into perspective, Drakensang has about 7000 textures and about 4500 to 5000 3D models (I don't have the exact numbers at hand because I'm not at the Labs right now), the runtime data for the whole game is currently about 4 GB in size. &lt;br&gt;&lt;br&gt;For level designers, there are 2 separate turnaround-time problems: updating the work machine with the new data from the last nightly build (this may take somewhere between half an hour and and hour or so), and the time it takes to test a change in the actual game (we're working with Maya as level design tool right now, not an ingame editor). &lt;br&gt;&lt;br&gt;We have a few holy dogmas at Radon Labs:&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Daily Build&lt;/b&gt;: everybody must work on the most current data which is at most 1 day old&lt;/li&gt;&lt;li&gt;&lt;b&gt;"Make Game"&lt;/b&gt;: creating a complete build must be fully automated, and happen on a central build machine&lt;br&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;The Toyota Rip Cord &lt;/b&gt;(don't know if this is translated correctly, it's the "Toyota Reißleine" in German): if there is no working build, production essentially stops until the problem is identified and resolved (and the responsible person has been ritually tared and feathered).&lt;br&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;One Tool For One Job&lt;/b&gt;: don't use several different tools for the same job (all 3D modeling is done in Maya for instance)&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;We also have a some other secret dogmas in our canon, but they don't affect the build system or level design work flow so I won't utter them here :)&lt;br&gt;&lt;br&gt;We could easily chicken out by giving up daily builds for instance. But this would most likely create "Ivory Tower" pockets inside the company. Tendencies like this happen all the time, they are dangerous for the project, and must be fought the instant they show up. &lt;br&gt;&lt;br&gt;Instead we stepped back and thought about how a perfect build-system and a perfect level-design system would look like. The whole problem is really 3 separate (but somewhat related) problems:&lt;br&gt;&lt;ol&gt;&lt;li&gt;reduce build time&lt;/li&gt;&lt;li&gt;distribution of build data to workplaces&lt;/li&gt;&lt;li&gt;reduce turnaround times for level-designers&lt;/li&gt;&lt;/ol&gt;&lt;br&gt;Point (1) is relatively easy. I think the only worthwhile improvement can be gained by distributing the workload across several build slave machines. We already invested serious optimization work into our Maya exporters, so there's not much more to gain there. Setting up a distributed build system is an interesting job, but not too complicated if you have control over all build tools.&lt;br&gt;&lt;br&gt;Point (2) is more interesting. The question here is "do we really need to distribute all the build data to all workplaces?". That's 4 GB of uncompressed data per day per workplace, but a level-designer typically only needs a fraction of that data during a normal work day, which typically looks like this:&lt;br&gt;&lt;ol&gt;&lt;li&gt;level designer comes in at the morning, and pulls the most current build data from the nightly build&lt;/li&gt;&lt;li&gt;level designer cvs-edits the files he needs to work on&lt;/li&gt;&lt;li&gt;level designer works inside Maya and several specialized tools, like dialog and quest editors&lt;br&gt;&lt;/li&gt;&lt;li&gt;level designer needs to check his changes in the game frequently (involves starting the game)&lt;br&gt;&lt;/li&gt;&lt;li&gt;in the evening, level designer cvs-commits his work and goes home&lt;/li&gt;&lt;li&gt;the build machine creates the new nightly build for the next day&lt;/li&gt;&lt;/ol&gt;&lt;br&gt;There are several problems here:&lt;br&gt;&lt;ul&gt;&lt;li&gt;in the morning, a lot of time is wasted to just update the runtime data of the workplace machines&lt;br&gt;&lt;/li&gt;&lt;li&gt;the local turnaround time to check changes in the game is too long (somewhere between 1 and 3 minutes)&lt;/li&gt;&lt;li&gt;when the level designer checks in his work in the evening, subtle collisions may occur with the work of other level designers (this is especially critical in "persistent-world-games" like Drakensang)&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Above a specific project size and complexity, level design becomes more and more frustrating because more and more time is spent waiting for results.&lt;br&gt;&lt;br&gt;Now here's the actual point of the whole post: What if level-design would actually be fun? We could improve the fun-factor a lot if the level designers would immediately see results, and could directly work together with others. What if level-design would be like mixture between a Wiki and a multiplayer game?&lt;br&gt;&lt;br&gt;Here's how we think our level design should work in the future:&lt;br&gt;&lt;ol&gt;&lt;li&gt;level designer comes in the morning, and starts the game in level-design mode&lt;/li&gt;&lt;li&gt;the game notifies the level designer that an update is available, updating only involves pulling a new executable&lt;br&gt;&lt;/li&gt;&lt;li&gt;the game connects to a central game server, which holds the actual game data in a database, and the graphical/audio content through a network share&lt;/li&gt;&lt;li&gt;the level designer creates, places and destroys game objects directly in the game, all changes are distributed via the game server to other level designers working "nearby"&lt;/li&gt;&lt;li&gt;to test the changes, the level designer presses a play button, and after a few (very few!) seconds, the editor will change into game-mode (it is very important to strictly separate the edit-mode from the game-mode, because application programmers should never have to care about level editor stuff)&lt;br&gt;&lt;/li&gt;&lt;li&gt;the ingame level editor is augmented with specialized tool windows written in C#, some of them generic (i.e. a nifty table view), some of them project-specific (i.e. an inventory editor)&lt;/li&gt;&lt;li&gt;in the evening, the level designer shuts down the machine and goes home&lt;/li&gt;&lt;/ol&gt;&lt;br&gt;So we would give up Maya as level design tool in favor of a "collaborative ingame level editor". The collaborative/multiplayer part sounds like a gimmick, but it's actually very important because it solves the data collision problem. Since all changes are immediately distributed to all level-designers, there's no danger that several conflicting data sets are created (the longer 2 separate data branches are evolving, the more likely collisions will occur which will be difficult to resolve).&lt;br&gt;&lt;br&gt;Up until a few days ago I would have scrapped the whole idea and declared it as impossible. Implementing an ingame editor which would suit all the different genres we are doing sounded like opening a can of worms. But in the end it isn't that difficult (for a distributed system it's actually necessary to have an "ingame-editor"). We already have a lot of the basic building blocks in place:&lt;br&gt;&lt;ul&gt;&lt;li&gt;We can pillage a lot of ideas from our current "Remote Level Design" system. At the moment, we can run Maya and the game side by side, and changes in Maya immediately show up in the game, this is nice for tweaking lighting parameters for instance.&lt;/li&gt;&lt;li&gt;Game data already lives completely in a lightweight local database (SQLite). This gives us a lot of advantages:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;a game entity is completely described by a simple set of named, typed attributes&lt;/li&gt;&lt;li&gt;a game entity always corresponds to a single row in a database table&lt;/li&gt;&lt;li&gt;all "other data" already lives in database tables (even hierarchical data, like dialog trees)&lt;/li&gt;&lt;li&gt;all data manipulations can be expressed with a very small subset of SQL (INSERT, UPDATE and DELETE ROW)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The only operations that must be supported by the generic ingame level editor must be "Navigate", "Create Entity", "Update Entity", "Destroy Entity", where creation is always a duplication either from a template or from another entity. More complex operations, or different views on the game data, will be implemented in C# tools which are connected through a standardized plugin interface. &lt;br&gt;&lt;/li&gt;&lt;li&gt;With Nebula3's TcpServer/TcpClient classes and orthogonal IO subsystem as base it should be relatively easy to setup the required in-game client/server system&lt;/li&gt;&lt;li&gt;We are already using some specialized editor tools written in C# (we did some of them in MEL before, and C# is a HUGE improvement over MEL especially for GUI stuff)&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;The devil is always in the details of course. But I think this is a pretty good plan to fundamentally improve our level design process in future projects.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7336353187193361451?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7336353187193361451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7336353187193361451' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7336353187193361451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7336353187193361451'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/10/ive-been-discussing-with-bernd-lot.html' title='Level Design And Build System Thoughts'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7985088916408037453</id><published>2007-10-16T09:25:00.000+01:00</published><updated>2007-10-16T09:26:36.479+01:00</updated><title type='text'>New Radon Labs Web Page</title><content type='html'>Our &lt;a title="new company web page" target="_blank" href="http://www.radonlabs.de/" id="orof"&gt;new company web page&lt;/a&gt; has gone live over the weekend! I really love the bright and colorful design. Apart from the fresh new design the other reason for the refactoring was better maintainability. Now that we're churning out several games a year it must be easy to update the website with game flyers and news. And it was suprisingly hard to get there. In the beginning we wanted to entrust an external company with our web page. But although Berlin is packed full with web designers it is suprisingly hard to find a good one worth his money. Most of them only seem to care about the artistic side, and more or less ignore usability and maintainablity. What we needed was a carefully engineered webpage that also had to look good. After some failed attempts we finally did it internally, and now we have a solution that's easy to maintain and integrates nicely into our company infrastructure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7985088916408037453?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7985088916408037453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7985088916408037453' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7985088916408037453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7985088916408037453'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/10/our-new-company-web-page-has-gone-live.html' title='New Radon Labs Web Page'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7760976614472200566</id><published>2007-10-14T15:49:00.000+01:00</published><updated>2007-10-14T16:14:34.314+01:00</updated><title type='text'>Google Docs</title><content type='html'>I recently had to wipe and setup my notebook (it's amazing how fast it feels now again, XP really does rot over time), and with it went the pre-installed Microsoft Office (which I just noticed today). But from time to time I have to write a proper document, nothing fancy, all I usually require is to structure the document with different types of headings, and to insert an image or a table here and there. I'm also often switching between my private notebook which I carry around everywhere and my work desktop, which sometimes involves copying said documents around manually. So in lack of an installed MS Word I gave Google Docs a try, and so far I like it. It even makes a nice blog editor, the builtin Blogger editor messes up source code for instance, but with Google Text everything is ok:&lt;br&gt;&lt;br&gt;&lt;blockquote&gt;Ptr&amp;lt;MyNS::MyClass&amp;gt; myObj = MyNS::Create();&lt;br&gt;IndexT i;&lt;br&gt;for (i = 0; i &amp;lt; myObj-&amp;gt;NumItems(); i++)&lt;br&gt;{&lt;br&gt;&lt;div style="margin-left: 40px;"&gt;// a comment&lt;br&gt;&lt;/div&gt;&lt;div style="margin-left: 40px;"&gt;myObj-&amp;gt;ProcessItem(i);&lt;br&gt;&lt;/div&gt;}&lt;br&gt;&lt;div style="margin-left: 40px;"&gt;&lt;/div&gt;&lt;/blockquote&gt;Instead of Tab, one must use the "Indent More" and "Indent Less" functions, otherwise the indents will disappear when exporting to Blogger, but all in all this is a huge step forward from Blogger's builtin editor.&lt;br&gt;&lt;br&gt;Let's see if tables work as well:&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;table id="yu10" bgcolor="#ff6666" border="2" bordercolor="#000000" cellpadding="3" cellspacing="0" height="57" width="317"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="50%"&gt;Bla&lt;br&gt;&lt;/td&gt;&lt;td width="50%"&gt;Blub&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr bgcolor="#ffff99"&gt;&lt;td width="50%"&gt;123&lt;br&gt;&lt;/td&gt;&lt;td width="50%"&gt;234&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br&gt;Nice :)&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7760976614472200566?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7760976614472200566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7760976614472200566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7760976614472200566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7760976614472200566'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/10/google-docs.html' title='Google Docs'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1173164079860127789</id><published>2007-10-07T12:32:00.000+01:00</published><updated>2007-10-07T13:43:34.246+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>In Praise Of Ninja Gaiden</title><content type='html'>So I finally played through Ninja Gaiden (Black) in Normal difficulty, boldly moved on to Hard difficulty - which by the way gives a whole new meaning to the word hard - got totally destroyed at the Alma boss battle, and immediately started a new session on Normal again. That's how f*cking cool Ninja Gaiden is. The first play-through is just standard procedure to become familiar with the environments and to know the story just enough to ignore it in the following play-throughs. After these minor nuisances are put aside, the game becomes the true Ninja Gaiden, reduced to the gamer on one side and Ryu's weapon on the other, connected through the game pad. And this essence of the game, unleashing combos, Hayabusa's unbelievable moves, the perfect feedback through audio, gore and rumble is what sets Ninja Gaiden far above all other fighting games I have played so far.&lt;br /&gt;&lt;br /&gt;Playing NG is almost like an exercise in meditation. The moment one loses focus and allows the mind to wander off the disciple is mercilessly punished. The difficulty level of Ninja Gaiden is the stuff of legends. But the game is never unfair. Becoming better at the game is purely a matter of training and honing one's skills, and never of pure luck. Sometimes another weapon, a new combo or another way to use the environment makes all the difference, but most of the time it's simply about not losing focus and keeping calm.&lt;br /&gt;&lt;br /&gt;So in conclusion I award Ninja Gaiden a score of 11 out of 10, and that's after deducting 2 points for lame story and setting :)&lt;br /&gt;&lt;br /&gt;I also played a few hours into Blue Dragon, enough to realize that old-school JRPGs are simply not my thing. Conan is alright but the combat lacks oompfh (maybe I'm spoiled by NG). I'm also feeling a slightly suspicious urge to play Dynasty Warriors (Empires) which I cannot really explain. There's something fascinating about the 3 levels of the game (the turn-based strategy phase on the top level, the Z-like elements of conquering bases during the game, and finally the pure hacking and slaying on the lowest level) which shines through the layers of bad graphics and voice acting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1173164079860127789?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1173164079860127789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1173164079860127789' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1173164079860127789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1173164079860127789'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/10/in-praise-of-ninja-gaiden.html' title='In Praise Of Ninja Gaiden'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7582679562830411448</id><published>2007-09-27T15:05:00.001+01:00</published><updated>2007-09-27T15:17:59.791+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Nebula3 September SDK</title><content type='html'>Here's the &lt;a href="http://www.radonlabs.de/internal/n3sdk_sep2007.exe"&gt;Nebula3 Sep 2007 SDK&lt;/a&gt;. This is - as always - work in progress.&lt;br /&gt;&lt;br /&gt;Some of the new stuff:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;new and improved HTTP debug pages&lt;/li&gt;&lt;li&gt;added some more subsystem docs&lt;br /&gt;&lt;/li&gt;&lt;li&gt;new Base namespaces which contains all XxxBase classes (mainly to keep the Doxygen documentation clean)&lt;/li&gt;&lt;li&gt;work-in-progress Lighting subsystem with dynamic spotlights and soft shadows&lt;br /&gt;&lt;/li&gt;&lt;li&gt;RenderTarget resolve-to-texture more flexible (resolve texture can have different size from the render target, and can resolve into a sub-rectangle of the resolve texture)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Compatibility info:&lt;br /&gt;&lt;br /&gt;The Test Viewer has been tested on nVidia 6600 and 7800 cards only. The 6xxx cards don't seem to support texture filtering on G16R16F textures, thus the shadow edges won't be properly smoothed (they still look quite ok though). I think the ATI cards are also unable to filter FP textures. The proper solution would be to implement the linear filtering in the shader. This is planned but not implemented yet.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;-Floh.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-7582679562830411448?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/7582679562830411448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=7582679562830411448' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7582679562830411448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/7582679562830411448'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/09/nebula3-september-sdk.html' title='Nebula3 September SDK'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-2468448979776421314</id><published>2007-09-25T20:31:00.000+01:00</published><updated>2007-09-25T20:42:25.100+01:00</updated><title type='text'>Nope...</title><content type='html'>I give up, I seriously can't take the pain any longer. No Halo for me until I can get my hands on the english version. Whoever's responsible for the german audio track in Halo3 either needs to be fired or promoted to a position where he can't do any more harm. Why oh why couldn't they simply keep the original audio track and provide german subtitles?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-2468448979776421314?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/2468448979776421314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=2468448979776421314' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2468448979776421314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/2468448979776421314'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/09/nope.html' title='Nope...'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-8591715180368223617</id><published>2007-09-25T19:49:00.000+01:00</published><updated>2007-09-25T20:08:46.030+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>German Halo3 WTF???</title><content type='html'>Nooooooooo........                 ...... oooooooh!!!&lt;br /&gt;&lt;br /&gt;I can't believe this shit! No English audio track in Halo3? It would be ok if the German voice track wouldn't be such a terrible piece of shit. Seriously who did they hire to do the voice overs? Interns? Halo fanboys? It is very easy to get very good voice actors in Germany for a reasonable price. People who actually dub movies as their profession, not some backyard junkies who apparently did the Halo3 voice overs. What an epic fuckup. The voice acting in Halo3 would be just barely ok for a porn movie, not Microsoft's flagship game on the 360.&lt;br /&gt;&lt;br /&gt;This is going to be hard...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-8591715180368223617?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/8591715180368223617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=8591715180368223617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8591715180368223617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/8591715180368223617'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/09/german-halo3-wtf.html' title='German Halo3 WTF???'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-377548857730613844</id><published>2007-09-25T16:06:00.000+01:00</published><updated>2007-09-25T17:28:10.257+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Smooth Shadows</title><content type='html'>I'm currently working on the dynamic shadow system. This is a shot from the PC-version with 2 shadow-casting spotlights (animated lights, it actually looks much cooler in motion):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_cWdorEDEaNg/RvkkMIYAEFI/AAAAAAAAAB8/5L0PcndkNeo/s1600-h/shot1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_cWdorEDEaNg/RvkkMIYAEFI/AAAAAAAAAB8/5L0PcndkNeo/s400/shot1.png" alt="" id="BLOGGER_PHOTO_ID_5114158642681090130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I have decided to use &lt;a href="http://www.punkuser.net/vsm/"&gt;Variance Shadow Mapping&lt;/a&gt; in Nebula3, a relatively new approach which allows the shadow buffer to be linearly filtered. This is a big win because post-process filters can be applied on the shadow buffers, and all the hardware filtering features of the graphics card to fight aliasing (mipmapping, min/mag filtering, anistropic filtering, etc...) can be used when sampling the shadow map. It produces wonderfully smooth shadows from relatively low-res shadow buffers (the scene above uses 256x256 shadow maps).&lt;br /&gt;&lt;br /&gt;The current implementation uses one "big" shadow buffer (512x512, pixelformat is G16R16F) which is re-used for all shadow-casting light sources:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_cWdorEDEaNg/RvkmK4YAEGI/AAAAAAAAACE/17KITEmAULw/s1600-h/vsmrenderbuffer.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_cWdorEDEaNg/RvkmK4YAEGI/AAAAAAAAACE/17KITEmAULw/s400/vsmrenderbuffer.png" alt="" id="BLOGGER_PHOTO_ID_5114160820229509218" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This is then downsampled to 256x256:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_cWdorEDEaNg/Rvkmu4YAEHI/AAAAAAAAACM/0fvhn5EiwHc/s1600-h/vsmdownscale.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_cWdorEDEaNg/Rvkmu4YAEHI/AAAAAAAAACM/0fvhn5EiwHc/s400/vsmdownscale.png" alt="" id="BLOGGER_PHOTO_ID_5114161438704799858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Finally the downsampled buffer is blurred into a shared shadow buffer which stores the shadow buffers of all active shadow casting light sources into a single texture:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_cWdorEDEaNg/RvknCoYAEII/AAAAAAAAACU/QbSJyHbTIqk/s1600-h/shadowbuffer.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_cWdorEDEaNg/RvknCoYAEII/AAAAAAAAACU/QbSJyHbTIqk/s400/shadowbuffer.png" alt="" id="BLOGGER_PHOTO_ID_5114161778007216258" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The pixel junk in the right half are the two unused slots, since there are only 2 (out of currently 4) shadow casting light sources in the scene. A texture array would be a better solution here, because at the moment sampling will "leak" into the neighbouring shadow buffer (for spot lights this isn't a big problem, since this will happen outside of the light cone). But texture arrays don't exist on DX9, so unfortunataly that's not an option.&lt;br /&gt;&lt;br /&gt;There's still a lot of work to do on the lighting system, but the intermediate results look very promising. I think I will first bring the 360 version uptodate before moving along. It's lagging behind a few days now.&lt;br /&gt;&lt;br /&gt;I have started to play through Ninja Gaiden Black again. Even among current 360 titles it would still look quite good, and it runs wonderfully on the 360 in 720p and 16:9. I finally want to beat the game on Normal (first time I only managed Ninja Dog... yeah I know). Everything about this game is simply kick-ass (well... except from the "story", yawn...). A real f*cking shame Team Ninja didn't release Sigma on the 360 as well. This was actually the only time where I was tempted to get a PS3, but... I seriously can't justify spending 600 Euro just for one game (which I already played).&lt;br /&gt;&lt;br /&gt;I also got Halo3 today, I didn't expect to see it on shelf already (European launch is tomorrow). It stood there right amongst all the old 360 titles. Germany is still PC-land. No doubt ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-377548857730613844?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/377548857730613844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=377548857730613844' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/377548857730613844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/377548857730613844'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/09/smooth-shadows.html' title='Smooth Shadows'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_cWdorEDEaNg/RvkkMIYAEFI/AAAAAAAAAB8/5L0PcndkNeo/s72-c/shot1.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-4384780895238476786</id><published>2007-09-19T17:03:00.000+01:00</published><updated>2007-09-19T17:24:40.760+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Nebula3 State Switch</title><content type='html'>A couple of interesting things have happened recently here at the labs:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Nebula3 has now the status of an official Radon Labs project, which means it has a budget and two of our elite-veterans (Johannes and Malte) will start working fulltime on Nebula3. This will accelerate development immensely. One or even two prototype projects will accompany N3 development which will define clear "real-world-goals" for feature planning. I feel this is exactly the right time to add manpower because all the important architectural decisions have happened, and now it's time to (a) broaden the feature set, and (b) start to revise and "port" Nebula2 and Mangalore subsystems which don't need a complete redesign.&lt;/li&gt;&lt;li&gt;Our first Wii devkit has arrived (actually, it arrived already a few weeks ago), and now with the additional forces added to N3 development, we're going to start a Wii N3 version which will be developed side by side with the 360- and PC-version.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-4384780895238476786?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/4384780895238476786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=4384780895238476786' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4384780895238476786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/4384780895238476786'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/09/nebula3-state-switch.html' title='Nebula3 State Switch'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-1274775663050918031</id><published>2007-09-12T18:50:00.000+01:00</published><updated>2007-09-12T19:03:40.504+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xbox360'/><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><title type='text'>Status update</title><content type='html'>I'm in the middle of the lighting implementation. Here's a little screenshot from the 360 version:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_cWdorEDEaNg/RugoS-4IG1I/AAAAAAAAAB0/CkZKOPFQkaY/s1600-h/n3lighting.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_cWdorEDEaNg/RugoS-4IG1I/AAAAAAAAAB0/CkZKOPFQkaY/s400/n3lighting.png" alt="" id="BLOGGER_PHOTO_ID_5109378083832994642" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Please excuse the crude lighting setup, this is for testing so it needs to be somewhat exaggerated. The model is from Drakensang, so it isn't actually modelled to be displayed upclose like this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2948438400037317662-1274775663050918031?l=flohofwoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flohofwoe.blogspot.com/feeds/1274775663050918031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2948438400037317662&amp;postID=1274775663050918031' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1274775663050918031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2948438400037317662/posts/default/1274775663050918031'/><link rel='alternate' type='text/html' href='http://flohofwoe.blogspot.com/2007/09/status-update.html' title='Status update'/><author><name>Floh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_cWdorEDEaNg/RugoS-4IG1I/AAAAAAAAAB0/CkZKOPFQkaY/s72-c/n3lighting.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2948438400037317662.post-7603541143778049996</id><published>2007-09-02T13:10:00.000+01:00</published><updated>2007-09-02T14:36:42.452+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nebula'/><category scheme='http://www.blogger.com/atom/ns#' term='Gaming'/><title type='text'>Even more HTTP (and some Bioshock)</title><content type='html'>Last HTTP post, promised :)&lt;br /&gt;&lt;br /&gt;I've added image support to the HTTP server this Saturday. Turns out no Base64 encoding is necessary (don't know why I assumed this), it's perfectly fine to just send the raw image data over the line. I wrote a StreamTextureSaver class which can save the content of a texture into a stream in a couple of formats (JPG, BMP, PNG and DDS). It's platform-specific and just uses the D3DXSaveTextureToFileInMemory() function on Win32 and Xbox360, so the Nebula3 code is really small. To send a texture to a web bro
