Introducing TK_ObjFile.hIntroducing TK_ObjFile.h

January 02, 2016

HandmadeCon 2015

Late last year, I was lucky enough to attend HandmadeCon 2015. It was a great and inspiring series of talks. After the talks, and some dinner and drinks and lots of geeky programming talk, I was inspired to start a "small" project that I had been thinking about for ages. I had a few more hours sitting around at the airport the next morning, and even kept working on it on the flight until the turbulence got so bad that I couldn't type (not even joking).

I made a good start, and then over the christmas holidays I had a lot of time sitting around while people cooked things or ate things or planned our day, and managed to finish it up. The result: tk_objfile.h.

TK_ObjFile OBJ

tk_objfile is a simple, header-only, single-file .OBJ file loader. It has zero dependancies and does no allocations, parsing in place and using only scratch memory passed in by the caller. The result, hopefully, is an easy way get triangle data out of an .OBJ file for any project.

This was heavily inspired by the stb_ family of libraries by Sean Barrett, and also by Casey Muratori's Handmade Hero series. That's the style of programming I learned back in the day (though I'm not as good as Sean or Casey), and that's how I used to write code. Then C++ came along, and I started writing things more enterprisey, and using terrible things like boost, even dabbling in template metaprogramming (an obfuscation technique that makes you feel smart, your compiler slow, and your code unfixable). Slowly, I came to the dawning realization that the code that I actually kept reusing, the code that still worked in new projects, turned out to be the simpler, C or vanilla CPP style code. I gradually recanted all the c++ nonsense, but I still felt guilty about it until I started watching the handmade hero stream. I can't claim it was fast to write this way, reimplementing stuff like atof and lacking any data structures, but it was fun to do. Anyways, this was a good exercise to get back to a minimal style and hopefully produce something useful.

OBJ Files

To paraphrase, OBJ is a terrible format, but it's better than all the others. Maybe not better, but it's usually the shortest path to get things out of a 3D authoring package. If you can live with only having position, ST and normals, it's quick and easy. (btw, I'd LOVE someone to make an OBJ-like format that was just a tiny bit more extensable, textual and easy to parse but allowing more custom uniform or per-vertex attributes).

Now, parsing an OBJ file is not a difficult task. In fact, if you're learning programming, I would highly reccommend it as an exercise. It's simple enough to get working in a few hours, it's useful in the real world, and there's no shortage of examples to test on. I've written OBJ parsers many times before. And therein lies the problem, I keep rewriting it. I kept not being able to re-use my previous ones, maybe it was using a vector/matrix library that I wasn't using anymore, maybe it was using stl and I didn't want to drag that in just to load an OBJ file, maybe it made assumptions about normals or geometry that were fine for a previous project but didn't work for a current one.

TK_ObjFile Monkey

Also, the one tricky detail after writing a handful of these tends to be handling materials. I tend to name my materials with the name of the texture in blender, that way I can export an .OBJ with multiple materials instead of having to split and keep track of a bunch of subobjects. Parsing these and batching the triangles by material is annoying and error-prone, but useful enough that I wanted to have that. So I wanted to make sure I made a loader that would handle multiple materials in a nice way. And if you don't care about the materials, you can just ignore it and don't have to do any extra junk to iterate over the material groups or anything.

Usage and Availability

The library is available at tk_objfile on GitHub. It's released under the MIT license, so you should be able to use it in any project, commercial or non-commercial.

The API tries to be simple: you give it the contents of an .OBJ file, and it hands you a bunch of triangles. It's a little weird since it's kind of a generator, based on callbacks, but that's the way I've used it in the past that has worked best for me. You can read more about the usage details on the github page, and in the header file itself.

I'll probably eventually make an "simple mode" wrapper that uses the C stdlib to do the file read and allocations and stuff, and just hands you an array with a bunch of triangles. Doing that seems obvious, but that makes a lot of assumptions about the calling program, and can end up being more work to rearrange the data. Of course, when those assumptions fit, and often they do, it's handy to have a simple one-shot API.

Also, fair warning, this is pretty untested, and there are probably bugs in there.

ObjViewer

I wrote a simple .OBJ viewer as a test case, based mostly on the glfw example from IMGUI. It also uses stb_image for loading textures. The code is quite messy and horrible, and the viewer is buggy and nearly unusable. How's that for a sales pitch? But I figured it was better to include it as something is better than nothing. I might continue to improve it and clean up and add features, but don't hold your breath (I'm actually not even using .OBJ in my personal pipeline anymore, which makes this project even more silly).

TK_ObjFile Hugzilla

The viewer does handle multiple materials, and draws them each with a different tint color. Also, if you name a material with the same name as a .png file in the current directory, it will load that file as a texture map (as in the Hugzilla example above).

TK_ObjFile Bust of Ajax

I didn't really try especially hard to make this fast, but the handmade style does kind of lend itself to performance, and it turned out pretty quick. It parses the ajax_jotero_com.obj mesh (50MB, 544k triangles) in 700ms, which is maybe not great for a AAA game pipeline that processes tens of thousands of objects, but if you're working on such a pipeline, you probably shouldn't be using .OBJ in the first place. For comparison, blender loads that same .OBJ in 21 seconds. But of course blender is doing a lot more than just parsing it. But anyways, it's pretty fast.

Conclusion

This was a fun side project for me. It was fun to go back to writing code in a "from scratch" style, and hopefully this will be useful to someone. At least, I'm pretty sure that I'll never have to write another OBJ parser again for my own stuff, which is worth it right there.

Let me know if you have any feedback or suggestions, through email, or a comment on this post, or on twitter (@joeld42). Suggestions or pull requests are welcome!

DevBlog 3 - It's PlayableDevBlog 3 - It's Playable

November 17, 2015

Devblog

I've been busy with other things for the last few weeks: We had a Hackathon at work (I won, yay), kids and Halloween events. I made it to Day of the Devs which was a lot of fun, even though I didn't get to try any VR games because of the insane wait times. In general just lots of general turmoil, but I did ultimately manage to get back to the project and make some progress.

No video this time, but instead you get a playable build. Stay tuned...

What I've done since last time

I think I fixed the stability issue, I had hacked some things in hxcpp to get it to build on tvOS, meaning to go back and fix them properly later, but of course promptly forgot all about it. Once I realized that, and I didn't even need to hack them in the first place, I was able to build and I haven't seen the problem in a while. There are still some ugly race conditions and potential crashes at startup (I blame SDL) that I need to sort through, but I haven't seen the gc related crash in a while. Then again, I've been mostly working on the web target (muuuch faster iteration) so maybe I'm just deluding myself.

Gameplay Screen -- Flight

So I've been hammering on the gameplay, trying to get the core loop finished. It's not entirely complete, and a lot of things are extremely oversimplified from what I have in mind, but it's working. You can fly around the map, buy and sell resources and make profits. Currently, it's extremely unbalanced and unfair, most of the prices and map are arbitrary, but at least you can get the idea of the gameplay.

Gameplay Screen -- Map

Probably the biggest change is going to be that a crash won't lose everything, you'll be able to Salvage, and regain most of what you lost. That's pretty essential in a game where you crash all the time. Still, it's going to be an interesting system to balance, since it is kind of a risk-management tradeoff.

Gameplay Screen -- Preflight Buy

So since I'm trying to be transparent about the development, I figured I might as well post the builds as I go, at least for the web target. This isn't alpha, this isn't even early-access, this is just raw work-in-progress dev builds, so don't expect much. It's plenty buggy, if the gameplay feels unfinished or crappy, that's because it is, come back in a few months and try a future build!.

ps. The game name is using an old placeholder. Ignore that.

DEVBLOG 3 EARLY BUILD

If you want, you can try a version with a random map and random prices for a little variety.

DEVBLOG 3 RANDOM MAP

Try it out. You can click on the map nodes to pick where you want to fly to. Press the 'z' key for the controller button, to launch the ship, etc. The preflight dialog shows how much you can buy each resource for, and how much it sells for at the destination. So "ore $2/$5" means you can earn $3 per ore you buy if you don't crash. See how many coins you can earn.

What’s Next

I'm going to pause on the gameplay for a little while, and focus on my favorite part: Graphics. I want to figure out what render passes/shaders I'm going to have, so I'll know what kinds of textures I'll have to paint and also have a rough idea of how much geometry I can push. Set up graphics budgets and targets, etc.

So my goal for next time, and this will certainly take more than a week, hopefully will be able to work on this some over the Thansgiving holiday, is: get the shaders more or less finalized, build out a few assets (walls parts or something) to a final level of polish, and come up with a graphics budget for the tvOS build so I know how many batches/triangles I can push through with whatever shaders and view distance I decide on.

Luckily, and not entirely by accident, it's just a ship in a tube, so there's a whole lot of visibility calc, LOD, occlusion, and other scene issues that I just don't have to worry about at all.

That's it for now. Next time, hopefully some fancy shiny screenshots.

Previous Page

Page 2 of 8

Next Page

Sign up to receive news, updates and promo codes!

Mailings are infrequent (fewer than once a month).

 
Copyright © 2016 Tapnik