Archive for the ‘Code’ Category

Convex Hate

Sunday, May 11th, 2008

The problem I’m facing is a seemingly tough one. What I want to allow ToeTag to do is to import triangulated meshes from a modeling program (in my case, Cheetah 3D) and then break that mesh down into convex chunks when it writes the MAP file out for compiling.

It’s tough because I can’t quite come up with a routine that will work for any arbitrary mesh. I can get it to work on some meshes but not others. I think it’s worth the effort though because when it works it will allow so much more expression in my level design.

Coding, coding…

glDrawFastAsHell

Tuesday, April 29th, 2008

I took some time off from my remix level to look at the ToeTag source again. The editor was getting a little choppy when the entire level is visible and I wanted to see what I could do to fix that.

The answer, it seems, is glDrawArrays. Holy crap! It takes some massaging of the data each frame to get it into contiguous arrays but, man, once it’s in there you can blast polygons to the video card. I can now work on my level with the whole thing visible. There are lots of places I can leverage glDrawArrays still so it will only get faster in the future.

Once I get as much as I can drawing through arrays, I’ll post a new version of ToeTag.

Very happy!

BSP Blues

Sunday, March 30th, 2008

I decided to try something out yesterday. I’m trying to figure out how to get an OBJ file to integrate with ToeTag in a seamless fashion. I had many ideas but then came up with the one that I felt was ideal : have QBSP simply insert those triangles directly into the resulting BSP! Why fool around with trying to create convex shapes from the OBJ file or extruding the polys backwards or other techniques that can get messy?

Well, because the QBSP code is horrifically complicated. Well maybe not for some people but for me, it is. I can’t make heads or tails out of what Carmack is doing in there. Global variables everywhere, obscure variable names, oddly structured function calls - ye gods. So that idea is dead. I thought that I was close at one point as I had it reading the triangles in and I was inserting them into the BSP but lots of stuff was breaking and they weren’t rendering and … well, just forget it.

I’m going to do a more traditional implementation of it now. ToeTag will read the triangulated mesh into the editor, break it down immediately into a set of brushes and then you can work with it freely.

I will offset the pain of this somewhat by implementing a feature that I will call “Quick Groups”. You’ll be able to select a set of brushes, hit CMD+G, and then those brushes will work as a group. If you double click on one, it will select all of the others in the quick group. Any imported triangle meshes will automatically go into their own quick group. Should work well enough I suppose although I really would have liked to have gotten the QBSP solution working. I guess that’ll have to wait until someone who speaks Carmack better than I do can take a look at it.

QuakeC Char Emitter

Wednesday, March 5th, 2008

So I was struggling with trying to set up an ending cinematic screen for Qonquer. I wanted to do a screen where it would spit out some stats on your game and give you some closure rather than just sitting there staring up from the floor in your dead body.

However, when I tried to customize the text being sent to the SVC_FINALE screen in QuakeC I discovered that you can’t send a dynamic text block. You can only send a static string. Even better, you can’t even send multiple strings. You can only send one if you’re using the WriteString function. Nasty.

So Preach over at func_msgboard gave me a link to some source code that included routines for spitting out chars to a channel in QuakeC. There were 8 versions of the function, each sending from 1-8 characters at a time to the channel (I named them pr1() through pr8() in my code base). I thought I was home free. Nope! Those emit values, not characters. Which means that if you want to spit out, for example, the word “Qonquer” you need something like this in your code:

pr7( 81,111,110,113,117,101,114 );

Those numbers are the ASCII character codes for each letter. Yeah, not exactly intuitive to read OR to write.

So what I ended up doing was writing a real simple Cocoa application to help me out. It will take a text string and split it up into the necessary function calls to get that text into the SVC_FINALE screen.

For example, let’s say I wanted to spit out “[Qonquer] - game over!”. I would use my program and it would generate this:

// [Qonquer] - game over!
pr8( 91,81,111,110,113,117,101,114 );
pr8( 93,32,45,32,103,97,109,101 );
pr6( 32,111,118,101,114,33 );

As you can see, it breaks the string up into multiple calls because QuakeC can only handle 8 arguments in any given function. It also emits a comment line at the top so you can see what those lines are supposed to be emitting.

Here’s a screenshot of the utility in action:

quakecemitter.jpg

I need to add some checkboxes and things to this screen to support adding newlines and things like that but this is basically it! This will help me out a lot on this and future QuakeC projects. When it’s done, I’ll make the source available with the rest of the Qonquer mod.

Chains of Bugs

Monday, February 25th, 2008

Programming is funny sometimes. Qonquer spawns minions that will fight for you as the game progresses. They target other monsters and wage war on your behalf. However, they don’t really have the ability to handle zombies which have to be gibbed. Easy enough, I thought, I’ll just make them ignore anything with classname == “monster_zombie”. Well, that would have been simple except for the 1/2 hour debugging session where I finally figured out that I’m dynamically spawning monsters into the arena but not setting their classnames correctly. Once I fixed that, my code for ignoring zombies magically started working. Woot!

Multithreading Brings Joy

Sunday, February 3rd, 2008

I’ve been listening to Cocoa oriented podcasts and subscribing to RSS feeds in an attempt to get my knowledge base up to snuff. While listening to “Late Night Cocoa” I was happy to find that the most recent episode featured multithreading and the guest was the head Mac guy over at Google (aka guy who knows what he’s talking about). It was great! Very informative and it gave my wife many excuses to make nerd jokes at my expense.

At any rate, he talked about a pair of classes that remove 90% of the pain of multithreading. NSOperation and NSOperationQueue. Using those, I was able to replace all of my multithreading code in Phorg and now it runs faster, automatically scales based on system performance, and I don’t have to worry so much about locking and synchronizing. Look into those classes if you have any plans to delve into multithreading on the Mac. So worth it!

I’ve been able to add a bunch of multithreading to ToeTag today as a result of using these classes. Everything is a little faster from loading WAD files, to generating mipmaps, to loading MAPs, etc. It’s amazing how once you have multithreading at your disposal how you can suddenly see spots in your code that could benefit.

ToeTag Nearing Completion

Friday, February 1st, 2008

Someone commented that updates seem to be slowing down for ToeTag and all I can say about that is … Yes. I mean, it works. It does what I want it to do for the most part so that’s why the updates have slowed. If it doesn’t do something critical then please, by all means, let me know!

I’m going to spend a chunk of the weekend cranking up a 0.9 release and then after that we roll on to the 1.0 real version. And it’ll be, for all intents and purposes, done!

I’ll add stuff over time, sure, but I’m not going to add features simply because I can. I want to limit feature additions to things that will get used by a typical person making a Quake level. The old 80% design rule - add features that will please 80% of your users.

I also spent a little cash and got a new logo/icon done for the editor. Check it out! I think it’s pretty swanky.

ToeTag logo

I also uploaded the source code for my multithreaded versions of LIGHT and VIS if you’re interested in those for your own projects or what-have-you. The original id tools source code is in this directory as well so you can see what I based mine on.

Source Code

Enjoy!

Phorg

Monday, January 28th, 2008

Another project I have on the go is a picture viewer. I know, not that exciting, but it’s entire purpose in life is to allow me to learn more about Mac programming. It loads the picture thumbnails using multithreading and it allows dynamic resizing of the window and the thumbnails.

Here’s a look at the window so far:

phorg_1.jpg

I was starting to code up a zoom window for it yesterday - so you could double click thumbnails and see the picture in a larger window - but then I got to wondering if it was possible to use the Quick Look window that comes with Leopard. It turns out, it IS possible! It’s a bit of a hack but the code I found to do it wasn’t that bad to look at and it’s contained in a small area of the code base so I can replace it later if the hack breaks. I found the info here.

So I changed the code to behave like Quick Look does in the Finder. Pressing SPACE will zoom the selected pictures into the Quick Look window and pressing it again will close the window. It works!

phorg_2.jpg

Quick Look is great. Imagine the possibilities this opens up for the ToeTag texture browser. Muhaha.

In closing, here’s a movie of the pictures loading using multithreading. Why? Why not? You’re at work and you’re bored.

.: Watch it! :.

Multithreaded LIGHT & VIS

Saturday, January 26th, 2008

I decided to take a look at the LIGHT and VIS source today and see what would be involved with getting them to work multithreaded. I knew that id had put the code in there for their Alpha machines but that it was disabled for everyone else. It turns out the code was almost fine for OSX except for some function names I had to fix up and a tiny bit of code refactoring.

But the end result is awesome! It works!

Some sample timings I took:

DM4
Before:
LIGHT = 1 second
VIS = 8 seconds

After:
LIGHT= 1 second
VIS = 5 seconds

Cool, but not really all that exciting right? Look at this:

START
Before:
LIGHT = 14 seconds
VIS = 49 seconds

After:
LIGHT = 7 seconds
VIS = 35 seconds

That’s a 50% speed up for LIGHT and a 29% speed up for VIS!

Another one:

E1M2
Before:
LIGHT = 25 seconds
VIS = 37 seconds

After:
LIGHT = 13 seconds
VIS = 25 seconds

About the same gains. So it looks fairly linear in nature. Awesome!

One thing to note here is that this is with 2 threads. I have code in the utilities to detect how many CPUs or Cores you have and it uses that number of threads. Using more than that number would be inefficient and using less would be silly. For example, I have a dual core processor so I get 2 threads. If you had one of those new 8 core monstrosities, you would get 8 threads! I would love to see some numbers on those machines.

At any rate, this will be in the 0.8 release of ToeTag which will be along pretty soon. I want to add a few more things before I call it a new version.

You’ll know when you have the multithreaded tools because your output log will have some new lines in it:

==========================================
LIGHT
==========================================

—– LightFaces —-
extra sampling enabled
74 entities read
Using multithreading (2 threads)
lightdatasize: 60932
0 switchable light styles
1.0 seconds elapsed

==========================================
VIS
==========================================

—- vis —-
testlevel = 4
661 portalleafs
1900 numportals
Using multithreading (2 threads)
average leafs visible: 157
c_chains: 3088511
visdatasize:27319 compressed from 54863
30.0 seconds elapsed

Soon!

EDIT: Interested in the source code for these utilities? Click here!

ToeTag 0.6 - PowerPC Support

Saturday, January 19th, 2008

I released a new version today because I believe I’ve got all of the endian madness sorted out with PowerPC machines. Definitely lucky that I have an old iBook G4 laying around here that I could test on! If you’ve had trouble running ToeTag on your machine, try the latest version:

http://www.wantonhubris.com/toetag/Download.html

It still requires Leopard but it should be processor agnostic now. Let me know if it isn’t!

As a side note, the development of this version was interesting. I, of course, had to learn about byte swapping and such to make it work on PowerPC but I had to figure out how to work on the code on the little iBook.

The screen blows on that laptop, limited to 1024×768, so working on it directly was not realistic. So what I ended up doing was I set up the new Screen Sharing feature in Leopard and was able to work on the iBook through a window on my Macbook Pro. Sure, the window was still 1024×768 in size but at least I could use my good screen and my good keyboard to work on the code.

It’s not super fast to work through a network connection but it DID work, and far better than what I was expecting.

So I copied the code over to that machine, worked out the byte swapping and other issues, then copied the code back to my main development machine. Pretty painless and I never had to try and develop code on that little 13″ screen.

Rock on, Apple!