Archive

Posts Tagged ‘Development’

Blender Export Scripts

July 13th, 2010 Colin No comments

Inspired by the idea behind iDevBlogADay I have decided to continue to blog more, as I enjoy writing and sharing useful (and not so useful) information.

Today I’m going to talk about adapting Blender for use in game development, specifically for exporting textured 3D models from Blender for use in our games.

I am assuming you know how to make Blender work and have created a mesh with a UV texture map. The problem you’re having specifically is getting that mesh out of Blender. You could of course use one of the built in exporters, but this way is more educational, also sometimes it is good to have control over the format your mesh data is stored in. The file described here is pretty basic, but hopefully this gives you enough working knowledge of Blender’s guts to use this as a springboard to create awesomer things. Another thing to take into consideration is that Blender and OpenGL use slightly different coordinate spaces, but it is not hard to work around.

Anyway, the language of choice for Blender is Python. If you like tabs, you will like Python. Much like how LISP was invented by parenthesis fetishists, I suspect that Guido van Rossum has a thing for tabs.

So, let’s get crackin’! Fire up your favorite text editor and do the following:

#!BPY
"""
Name: 'MyMeshExport'
Blender: 248
Group: 'Export'
Tooltip: 'Export a MyMesh File'
"""
 
import Blender
import bpy

What this does is tells Blender that it’s a Blender Python script named “MyMeshExport”, runs on at least Blender 2.48 (you can change this as you see fit), and goes in the “Export” group. The imports hook into a bunch of Blender specific stuff including the scene.

Next, we’re going to specify the “write” function for the script. This is what is run automatically when you choose this script to export it.

def write(filename):
	out = file(filename, "w")
	sce = bpy.data.scenes.active
	ob = sce.objects.active
	mesh = ob.getData(mesh=1)

What this does is opens a file for writing, and hooks it to out, takes the currently active scene assigning it to sce, the currently active object and assigns it to ob, and then assigns the first mesh in ob to mesh. This assumes you have selected your object before you exported, and that object only has one mesh.

Next we’ll put in how many vertexes and faces there are in our mesh into the file. This will make life easier for our file loader:

	out.write('%i Vertexes\n' % (len(mesh.verts)))
	out.write('%i Faces\n' % (len(mesh.faces)))

Next we insert vertex co-ordinates:

	for vert in mesh.verts:
		out.write('v %f %f %f\n' % (vert.co.x, vert.co.y, vert.co.z))

This goes through each vertex in the mesh and inserts “v x y z” where x, y, and z represent the co-ordinates of the vertex.

Finally we write in information for each face in the mesh, including what vertexes make up the face, the vertex normals for that face, and the UV coordinates.

	for face in mesh.faces:
		out.write('f')
		for vert in face.v:
			out.write(' %i' % (vert.index))
		out.write('\n')
		out.write('n %f %f %f\n' %(face.no[0], face.no[1], face.no[2])
		out.write('n %f %f %f\n' %(face.no[0], face.no[1], face.no[2])
		out.write('n %f %f %f\n' %(face.no[0], face.no[1], face.no[2])
		for uv in face.uv:
			out.write('uv %f %f\n' % (uv[0], uv[1])
	out.close()
Blender.Window.FileSelector(write, "Export")

This is where the per-polygon information is spat out into your file. For each face it outputs “f v1 v2 v3” where v1, v2, and v3 are the indexes of the vertexes we exported previously.

Next we output the normals. In this simple example we’re going to assign the face normals to each of the vertex normals. This is because whatever Blender thinks the “smooth” per-vertex normals are has no basis in reality what-so-ever. If you want to get smooth normals, you will have to compute them yourselves. The normals are encoded as “n fn1 fn2 fn3” on 3-separate lines (one per vertex) where fn1, fn2, and fn3 is the face normal.

Finally we output the UV coordinates of the texture map. For each vertex in the face we get “uv uv1 uv2” where uv1 and uv2 are the UV coordinates of that vertex.

The last line in the file tells Blender to open it’s File Selector window and call ‘write’.

Once you save your file with an imaginative name like ‘myfileexport.py’ you can copy it to wherever Python keeps its scripts. This is different under different platforms obviously, though you can get that information here, which incidentally I discovered after writing all this is practically identical to my post, except I cover exporting UV coordinates. Possibly because this is where I learned this over a year ago and subsequently forgot. Mea Culpa.

Anyway, let’s finish this up. So you’ve put your script into your scripts folder. Now you need to update the menus in Blender to tell it that it’s there. So you go to the Python pane and go to Scripts > Update Menus. Then you can go to your scene, select your object then go to File > Export > MyMeshExport to save your new mesh for inclusion in your game.

GameFontMaker

July 7th, 2010 Colin 2 comments
GameFontMaker Icon

GameFontMaker

July 9th Update: GamefontMaker is now at 1.0.0 beta 2 and it’s also been released under the GPLv2. You can find the latest version and source over here!

It’s been a while since I’ve posted anything to the blog, so I figured I’d do something a bit special to try and get into the swing of things. So, I present to you what I think may be the first native Cocoa bitmap font creation tool for games, GameFontMaker!

At least, I think it is… Maybe… I didn’t do a lot of research, but I have seen a lot of fellow iOS devs wishing something like this existed for OS X, as the only other alternative runs under Windows.

Even if it isn’t, I was getting sick and tired of my really awful bitmap font creation tool that used FTGL, SDL and duct tape and generally produced hideous bitmaps without a lot of fudging of numbers. This is much, much better than that.

Anyway, GameFontMaker is currently in “beta” so don’t come crying to me if your computer explodes or anything. Though in my defense it hasn’t caused my MacBook to explode, and it was way less stable when I started it about 12 hours ago!

This is also my first Cocoa app, so forgive me if it’s a bit rough around the edges.

That being said, if you do find a bug or have a suggestion you could always drop me an email at: colin[at]celsiusgs[dot]com.

So, you’re itching to create some decent bitmap fonts for your game? Well, GameFontMaker is pretty easy to use. From the main window:

GameFontMaker Main Window

GameFontMaker Main Window

You can select the font by clicking on the “Fonts” toolbar button, doing so updates the preview. Once you’re satisfied with your selection, click “Export Font” which opens a file dialog. Choose the file name here, it will automatically choose a .png extension. Once you make sure you’re not overwriting an important system file or your taxes or what have you, click “Save”. This will invoke an ancient spell designed to end the world (and generate fonts) and will cause GFM to spit out a PNG file with all the printable ASCII characters in a line, also it will produce <filename>.png.xml which is an XML file that describes all the character dimensions. It has the following format:

<?xml version="1.0"?>
<fontdata>
	<glyph>
		<character> </character>
		<width>7</width>
		<height>25</height>
		<offset>0</offset>
	</glyph>
...
</fontdata>

Right now the output isn’t ideal for using directly as a texture atlas, but hopefully the PNG plus the XML file can be put to some good use. Once I get some more time I will add support for defining the PNG size and altering the XML output.

Anyway, GameFontMaker is free to use for all sorts of purposes, however if you do find it useful you could always have a look at my games or maybe follow me on The Twitters. Enjoy!

Chromodyne… HD!

April 3rd, 2010 Colin No comments

Well, the iPad is out and Chromodyne was successfully ported after a marathon session of epic proportions. Amusingly, Chromodyne HD was submitted after Chromodyne v1.1 and was approved before. Some may say I amuse easily, but I was amused.

The Port

Thanks to some experience writing game engines for other platforms before, about 90-95% of Chromodyne’s graphics code was already resolution independent. After updating my XCode to the 3.2 Gold Master, I clicked the handy little “Convert this project to iPad” menu option and was playing Chromodyne in the simulator in mere minutes! Though everything else was really horrible looking because none of the 2D assets were scaled properly and some of the menus looked like crap on the huge screen.

So really, most of my time was spent creating high-res 2D graphics (even though the cutscenes are pixel art, for the most part, those are seriously high-def pixels!) and fiddling with the perspective/view on the gamefield because it was way too freaking big keeping the same perspective as the iPhone version.

I don’t know about the final build yet, but the simulator in the GM release of the SDK didn’t have 3D acceleration! I can understand why some devs were reluctant to release their apps sight-unseen to the App Store.

The iPad Only Version

If anyone actually wonders why I went with a stand-alone iPad version of Chromodyne, the biggest motivator is that the app bundle for the HD version with its 1024×768 graphics assets is larger than the 20 MB OTA limit. Basically I still want people to be able to get the iPhone version over 3G.

The Price

I’m also selling Chromodyne HD for $1.99 instead of 99 cents. I figure the larger, higher resolution game experience warrants a slightly higher price point. We’ll see how that plays out in the days to come anyway… at least I can have a sale at some point without going directly to free. Definitely something I regret when I priced Chromodyne originally.

The Numbers

I’m half-tempted to post sales numbers for Chromodyne HD as time wears on. If anything to see how things are going. I’ve seen that the game lists for the iPad don’t have any top lists for subcategories yet, which is pretty bad news for small devs such as myself. Sales for Chromodyne have not been anything to write home about, but they’ve been steady at least.

Anyway it’s been a fairly exciting few days, and at least I can say I was here from the start. Whatever that actually means, only time will tell.


Thoughts on the iPad

January 27th, 2010 Colin No comments

Well, Apple finally released their oft-speculated-upon tablet, the iPad, today. The response I’ve been seeing across the interwebs has ranged from comments reminding me of the hubris inducing pessimism surrounding the launch of the iPod, to the completely ridiculous sort of grandstanding that comes about whenever the press catches hold of something that’s “going to change the world!”; like, how it’s going to kill the mouse and keyboard or something. That’s like saying the computer will kill paper and pens, or the Segway will kill walking, or… ingesting pop rocks and soda killed Mikey. See what I’m saying?

What about me? Small game designer/developer guy you probably haven’t even heard of until now? I think the truth lies somewhere in the middle, and the iPad is balancing on a knife-edge between success and failure.

Stick with me here.

I think where the iPad’s potential lies is as a beefed up PDA/planner with the capabilities of an eBook reader and some of the power of a laptop, like editing documents and viewing large videos, while still being in a small form factor with an amazing battery life.

The problem with the iPad, at least as far as I can tell, is that Apple has actually created the iPad’s worst competitor. By placing the iPad as a device in between PDAs and laptops, Apple believes that they are competing with inexpensive netbooks, but in reality, I think that the iPad’s biggest barrier for growth will be it’s older, yet shorter brother, the iPhone!

Look at it this way: the iPad instead of being a small laptop without a physical keyboard, ports, etc., is more like a large iPod Touch or iPhone without the phone and camera parts. People are going to look at their iPhone and think “why would I want an iPad? My iPhone does practically everything I need it to do and more, and it’s more portable to boot.” It’s an even worse value proposition if these people have laptops already. The problem is that by making the iPad behave more like an iPhone and less like a laptop, many people, I think at least, will view this as an iPad vs. iPhone question rather than an iPad vs. netbook or laptop question.

Don’t take this as me completely writing off the iPad. I don’t think it’s going to be a Segway, but I’m not really sure if it will end up being an iPhone or iPod. I do think it will find it’s place in the market, but I think that iPhone OS and the hardware may need to go through a few revisions before it can really get a proper foothold.

I suppose I should talk about gaming and the iPad while I have you here, seeing as that’s kinda my thing.

First off, I think that we’re probably going to see a divide between gaming on the iPad and the iPhone/iPod Touch. Nothing huge but because of the iPhone’s phenomenal success, I think that there will still be a massive demand for small form-factor games that specifically target the iPhone. On the other side of that coin I think that the iPad, by being larger with more power and having a higher resolution will allow more freedom of expression for game developers. But this is good! More choice is never a bad thing when it becomes trivially easy to port your software between these devices, you just have to make sure you design your software with an eye towards running on many devices (this was a good idea before the iPad, in case you didn’t get that memo).

Earlier today I read an article suggesting that the iPad was going to be end of the sort of small developer that found success on the iPhone because it allowed for small teams to produce small games but reach a large audience. I definitely don’t see that as an lesson to take away from the iPad. I do agree 100% that developing games on the iPad, specifically to take advantage of the iPad hardware, will be more time and money intense, however it’s not like the iPad is going to kill the iPhone. Hell, I’d even go so far as make the rash and wildly assumptive statement that most small iPhone devs can blissfully ignore the existence of the iPad and still be able to make a comfortable living selling their wares to iPhone owners (as they are legion).

My personal goal is to see Celsius Game Studios games on the PS3 and 360, so I’m not dreading the iPad. Quite the contrary, I view it as yet another exciting platform with a potential audience for my games.

Also, much like “Wii” humanity will somehow come to terms with “iPad.” You can quote me on that.

The Game Is Afoot!

January 19th, 2010 Colin No comments

Just wanted to drop you all a note saying that I am forging ahead with my plans to turn Celsius Game Studios into something more than a hobby in my spare time. I really do love creating video games and I’ve been thinking about making my own company to do this for over 12 years now, it’s unfortunate it took me this long to stop being afraid about “what if it doesn’t work” and just realize it’s more important to get out there and kick some ass and do awesome things. I’ll be spending the next few months easing out of my current job before I can fully spin up the turbines at Celsius. However I have started pre-planning my next title, which you will find out about soon enough ;)

I still have a lot of hard work ahead of me, business plans, and funding and all that crazy scary stuff, but rest assured this is the real deal. I just wanted to let everyone know that awesome things are in the pipes, but that I have a lot on my plate right now so I hope you’re understanding while I work on them all at the same time.

To that effect I wanted to say that I’m still working on the 1.1.0 update for Chromodyne, and it will be out Real Soon Now.

Things that will definitely be in the update:

  • Improved game timing, reducing the time between a match being made and the play field being active again
  • 3D lighting has been improved
  • Cutscenes are now skippable
  • Improved load times slightly and added spinner when loading

Things that I’m currently working on for the update, which will hopefully make it in:

  • Alternate control style, currently testing a few final candidates
  • Online leaderboards, working on securely transmitting scores

Until next time!

Anyone Out There?

September 29th, 2009 Colin 3 comments

I suppose people might actually be reading this thing, at least after PocketGamer.biz oh so graciously interviewed me for a feature on one-man/woman iPhone developers, so I should probably update a little more often!

I’m about… oh… 98% done Chromodyne so that’s pretty exciting! Once that’s done, it’s time to start The Next Big Thing™ and work on some stuff I’d like to see in v1.1 of Chromodyne.

I’d kinda like to do one of those “Questions for the Developer” things infrequently… so if you’re out there and have questions about iPhone development, I’d love to hear them :)

’til next time!

All You Devs Out There

August 2nd, 2009 Colin No comments

Let’s all take a moment to reflect upon Hofstadter’s Law: It always takes longer than you expect, even when you take into account Hofstadter’s Law.

It is always true. Always.

Optimizing for OpenGL ES

July 18th, 2009 Colin No comments

If you’re trying to get your OpenGL ES code to run really fast on the iPhone you have to take one very important piece of information into account: writing to memory on the iPhone is expensive. To that effect, I just got another >10fps in my 3D engine by precomputing vertex, normal and texture coordinate buffers for all my 3d models instead of writing to a generic buffer in my drawing loop as I had been doing. So basically when I call gl*Pointer calls, I point to the buffer in my model object.

It means I’m using up a tiny bit more memory per model (not per object, as they reference the models) but the performance increase is amazing and totally worth it.

Spinning Wheels

July 13th, 2009 Colin No comments

Much progress was to be had over the weekend, also much frustration… but my game code pretty much works on my iPod now! I’m so excited :D

First of all, I’ve decided to create a new law. Let’s call this law Colin’s First Law of New Platform Development. It is thus: “When developing on a new platform and your code fails in a spectacular fashion, don’t assume it is the platform’s fault for being new and strange. It is in fact because you’re an idiot and didn’t initialize a variable properly.” I’ll just go ahead and leave this here.

In other news, I will now tell you how to make a fairly decent method to shuttle input from the main thread to your game thread when working on the iPhone OS. It took me a while to hunt it down, so I’m sure if this ever shows up in Teh Googles someone might find it useful.

First of all, I created a class which is basically a FIFO of “event” objects. It’s pretty basic, but it will do the trick.

Initially, I figured all I needed was a boolean variable in the FIFO to let the system know if the FIFO was busy. Boy howdy was I wrong. You see, I discovered that the variable itself was being accessed simultaneously by the view controller and the game code causing it to crash horribly. So I’m like… clearly people do this sort of thing all the time, I just need to keep searching until I find a mechanism that allows this sort of thing. After some searching I learned about atomic operations, or operations that are guaranteed to happen within one processor cycle. This guarantees that only one thread will be operating on the variable at one time, thus preventing Michael Bay levels of explosive action in your code.

So, where do we find these atomic operations? Thankfully Apple has thoughtfully included some in the OS. I’m sure there are more elsewhere, but for my code I decided to use the functions in the scarily located <libkern/OSAtomic.h>. Really though, it’s not so scary! What we’re going to do is use a spinlock to resolve resource contention (the resource being our FIFO). Basically we give our game code and the view controller a pointer to an OSSpinLock variable and they both use OSSpinLockLock(OSSpinLock *); to fight it out for who gets first crack at the buffer. The reason I chose OSAtomic functions is because they are relatively lightweight, and this sort of resource sharing is fairly simple.

Anyway! To get this to work, you need to declare an OSSpinLock variable (it’s basically an integer) somewhere and pass a pointer to it to your view controller and your game code. Also you have to do the same with your event queue object. Because your view controller will probably be trying to send touch events before your game code has fully initialized, it is best to have the view controller call the functions to init the spinlock and the event queue.

A word of warning, most of my game code is in C++, as I’m really not very comfortable with Obj-C atm, but C++ code will happily co-exist with your Obj-C code. The only major caveat is if you’re calling C++ inside your Obj-C objects, the implementation files have to be .mm, not just .m so they are compiled as Objective-C++. Otherwise the compiler will just sit there and stare at you funny. This spinlock method should work with straight Obj-C too though!

Okay so I’ve created a few simple functions (in C!) to initialize and pass around the spinlock and the event queue. They live in eventsync.cpp:

#include "eventsync.h" //This includes OSAtomic.h and the header for the event queue
 
static OSSpinLock *lock; //static so it never goes away
static CGEventQueue *uiEventQueue; //same here
 
CGEventQueue *getEventQueue()
{
  return uiEventQueue;
}
CGEventQueue *getEventQueueAndInit()
{
   uiEventQueue = new CGEventQueue;
   return uiEventQueue;
}
OSSpinLock *getSpinLockAndInit()
{
   lock = OS_SPINLOCK_INIT;
   return &lock;
}
OSSpinLock *getSpinLock()
{
   return &lock;
}

Now that that’s sorted out it’s pretty easy to get started. In your view’s interface add a pointer for an OSSpinLock and your queue object. Then in the view’s init code (in my case initWithCoder), call getSpinLockAndInit() and getEventQueueAndInit() to set up your view’s pointers (in this case, lock and eventQueue). In your game code you’ll want to call getSpinLock() and getEventQueue().

WARNING: Stargate references abound. Now that you’ve spanned your two threads with the code equivalent of a wormhole, just like in Stargate, they can only work in one direction. So your spinlock is going to act like a DHD and will activate the wormhole and send SG-1 in the right direction, hopefully avoiding killing some hapless team member in the process.

Basically what we will do is use OSSpinLockLock() to try and set the spinlock variable. If the spinlock is already locked, it is in use somewhere else, so OSSpinLockLock() will loop until it is no longer locked. It is our responsibility to unlock the spinlock in each thread when we’re done with it or everything will stop working.

So before this post gets even longer, here’s the upshot. When we overload touchesBegan, touchesMoved, and touchesEnded (or other input methods) we’re going to do something like this:

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch *touch = [[event allTouches] anyObject];
   CGPoint touchLocation = [touch locationInView:touch.view];
 
   OSSpinLockLock(lock);
   //when the lock is free we can safely push events into the queue
   TouchEvent *ev = new TouchEvent;
   ev->type = CGE_TOUCHDOWN;
   ev->x = touchLocation.x;
   ev->y = touchLocation.y;
   eventQueue->pushEvent(ev);
   OSSpinLockUnlock(lock);//important to release the lock!
}

In our game code we’d have something like:

OSSpinLockLock(lock);
TouchEvent *ev;
while(eventQueue->getNumEvents())
{
   switch(eventQueue->topEvent()->type)
   {
      case CGE_TOUCHDOWN:
         ev = static_cast<TouchEvent *>(eventQueue->topEvent());
         //do stuff with the event
         break;
      }
      //Handle other events here
      eventQueue->delTopEvent();
   }
}
OSSpinLockUnlock(lock);

It’s as simple as that!

Til next time :)

Whee!

July 10th, 2009 Colin No comments

Well, I got my iPod Touch on Wednesday, so I spent about an hour to get a provisioning profile from Apple and to set up Xcode to work with that. I started an Open GL ES project and copied my 3D engine code into it and just kept beating it with a sledgehammer until it compiled. It was actually a fairly easy process overall.

I had already replaced all my immediate mode OpenGL calls with vertex arrays, but I discovered much to my horror that I was still using some unsupported calls. I cleaned that up and I figured out how to install GLU for the iPhone in the simulator and iPhone OS SDKs as well.

Then I realized that the iPhone’s GPU only supports power of two textures… oh great shades of 1998! I consulted the intertubes and found out how to use some GraphicsServices calls to scale my textures to a more appropriate size. This is in no way optimal mind you! Once everything is working properly as is, I’ll get a start on optimizing my textures and stuff like that, but this is a great start.

The next night I decided to start using a thread to run my game code instead of using the timer method as it creates a lot of overhead. If you end up having trouble with this, I have discovered for some reason you should initialize your GL buffers in the main thread instead of the game thread. I’m thinking it’s some sort of resource synchronization issue with the main thread and the forked thread.

So right now I sit with a working 3D engine and my next step is to capture touch input from the main thread and start pushing it into an event queue for my game thread to nom on. I suspect I will need a blocking mechanism while the game thread is doing it’s thing.