Thursday, May 31, 2012

BlackBerry GamePlay3D 2

The previous build is boring. Let’s kang some code from SDK sample 1. And by kang, I mean replace virtually all of the code.



Rubber Ducky, you’re the one!
Riveting. That number in the upper left is the FPS display. I don’t like it. Let’s mess with it.


Now if you have built the sample application you’ll notice that my build looks a bit different than yours. I did some work on automatic recognition of the target system, the build environment, and so on. This is relatively easy, but I made it difficult (three header files that will recognize pretty much every processor/build environment since 1980). I split the previous drawFrameRate function into two, making a new function drawText that drawFrameRate calls. I then added a new function, drawBuildString. All preprocessor definitions are strings (automatically selected, but I’m not posting that) with the exception of GAMEVERSION, which is a float. In any case, the relevant code looks like this:


// Debug vs Release
#ifdef _DEBUG
#define BUILD "Debug"
#else
#define BUILD "Release"
#endif

#define BUILDSTRINGPARAMS GAMENAME, GAMEVERSION, GAMESUBVERSION, __DATE__, __TIME__
, BUILD, OS_NAME, HW_PROCESSOR_NAME
#define BUILDSTRINGFORMAT "%s %1.2f%s.%s.%s.%s %s %s"

void Core::render(long elapsedTime)
{
   //…

   // Draw compile info
   drawBuildString(5, 1);

   // Draw the fps
   //drawFrameRate(_font, Vector4(0, 0.5f, 1, 1), 5, 10, getFrameRate());
   drawFrameRate(5, 15);
}

void Core::drawFrameRate(unsigned int x, unsigned int y)
{
   char buffer[16];
   sprintf(buffer, "%u FPS", getFrameRate());
   drawText(_font, Vector4(0, 0.5f, 1, 1), x, y, buffer);
}

void Core::drawBuildString(unsigned int x, unsigned int y)
{
   char buffer[128];
   sprintf(buffer, BUILDSTRINGFORMAT, BUILDSTRINGPARAMS);
   drawText(_font, Vector4(0, 0.5f, 1, 1), x, y, buffer);
}

void Core::drawText(Font* font, const Vector4& color, unsigned int x, unsigned int y, char* buffer)
{
   font->begin();
   font->drawText(buffer, x, y, color, 20);
   font->end();
}

Now we have a baseline to build a real application. My first concern is file system/network streaming. I want a system where I can precache octree nodes and stream them regardless of data source (the application does not know or care whether the data comes from the file system or the interwebs). Additionally, I want each level of the octree to contain a mipmap of the combined sublevels. By this I mean that if I load the top level of the octree, that level contains a lo-res version of all necessary data for rendering. Each subdivision (leaf) of the octree contains increased detail. We will see how well this goes.


Prior to that, I need to deal with file formats. Gameplay includes a proprietary bundle format (.gpb) that requires a proprietary tool to build (think Doom WADs back in the day - http://doom.wikia.com/wiki/WAD). It is a well thought out, comprehensive format. What seems to be lacking is support for compression and encryption. For this, I will use the public domain LZMA SDK that can run on ARM, x86 (actually 386 onward!!!), PowerPC, and so on. The question is how to do this. If I were designing this from scratch, I’d say that I would want to compress the data within the container. I want to minimize my impact on the SDK, and avoid unnecessary rewriting of the toolchain, so I don’t think that is the way to go.


What I think I need to build is a comprehensive Resource Management system. The Bundle code does a lot of this already; however, it appears to be path dependent. By this, I mean that assets are represented in code by their string path. If I want my rubber ducky model, I load it:


// Load mesh/scene from file
Bundle* bundle = Bundle::create("res/duck.gpb");
_scene = bundle->loadScene();
SAFE_RELEASE(bundle);

Then every time I want it I attempt:
// Get the duck node
_modelNode = _scene->findNode("duck");

This code isn’t checked, so if “duck” doesn’t exist in the scene, I crash. I don’t want to hardcode “duck” all over the place. And, I don’t want to crash if “duck” doesn’t exist. So what can I do with this?


So, to sum up, I need to build a resource manager with the following properties:

  • Transparent streaming from either local or remote file system
  • Precache capability
  • Intelligent unload capability
  • Mipmaps/Clipmaps/Level of detail (ideally the lowest level of detail will be compact enough to always be in memory)
  • Compression/Encryption support
  • Null (default, placeholder) models/objects
  • Ability to load resources individually or by node/cell
  • Centralized media manager not reliant on path or object strings
  • Reference counting for automatic release of memory?
A tall order, for sure. Many headaches loom ahead…

Friday, May 25, 2012

BlackBerry GamePlay3D

So this is the first in a series of blog posts that explore the cross-platform Gameplay SDK that BlackBerry (remember them?) is producing.
First thing to do is to explore www.gameplay3d.org and see what the capabilities of the SDK are.
Second thing to do is to clone the Git repository. I did this by using the quite nice (Metro style) Git for Windows application from windows.github.com.

For whatever reason, this app thinks that I have modified SDK files (32 of them!), even though I haven’t. This prevents me from changing branches (from master to next, for example), even if I discard the changes for every file (has to be done individually, very annoying).

The program has this annoying behavior on both of my Windows systems (one running Windows 7, the other running the Windows 8 Consumer Preview). So, if you want one of the other branches, I suggest simply downloading the .zip archive from Git. Use the “Clone in Windows” button to clone using the Metro app, or use “ZIP” to download the snapshot.

If that is not a concern (probably should not be), then GitHub for Windows is good enough at cloning repositories. One other annoyance – GitHub for Windows does not allow you to select the folder where repositories will reside. The default (when cloning the Gameplay repository) is %Userpath%\%Username%\Documents\GitHub\GamePlay, so fair warning. I’m sure GitHub will for the kinks out of the program eventually (at the time of this writing it is only version 1.0, just out of Beta).
So for the next part, I followed the directions in this post: http://www.gamefromscratch.com/post/2012/05/02/A-quick-look-at-RIM%E2%80%99s-Gameplay-12-SDK.aspx
The author does a great job of getting you up to speed quickly with a Windows app. Mobile platforms (Android and iOS) require quite a bit of additional work that I will not get into here. Start by running the gameplay-newproject.bat file in the gameplay directory.
Public Service Announcement: Build errors. C++ would not be any fun without them.

If you want to avoid them, I suggest keeping the project on the same hard drive as the gameplay sdk when prompted by the gameplay-newproject.bat batch file. Additionally, the batch file does NOT like path names with a space in them.

Make sure to add the gameplay.vcxproj project (located in your Documents or wherever you extracted the .zip to) as a dependency.

Then build! I am using Visual Studio Professional 2010, but it should build just fine in an Express edition if that is all you have. I would not recommend using a version older than 2010, though.
Great success. But boring.

Next time, we will spice this up a bit.
V/R
Jaegermeiste