Tuesday, December 20, 2016

Feedback

Some game developers dislike reading comments and feedback so much, that they completely stop doing that. In my experience, some of it is indeed downright abusive. I shrug it off by assuming the really threatening messages are written by kids, not adults.

But if you stop reading feedback, you will miss out on some real gems, be it for comedy-value, usefulness or endearing qualities.

Here are some of the most interesting responses I have received throughout the years.

Funniest (from long time follower apparently):


Most indignant:


Most litigious (and funny):


Most heart warming:


Most repetitive:


Most useful (So valuable, I should be paying for this feedback):


Saturday, November 26, 2016

Unable to find native library / findLibrary returned null

Ever since doing Android development in 2012, I've been getting crash reports that showed my game was failing to load the shared object library that contains my native code.

This could manifest itself as a:

Unable to load native library: /data/data/com.sample.teapot/lib/libTeapotNativeActivity.so
or sometimes a findLibrary returned null:
E/AndroidRuntime( 7344): java.lang.UnsatisfiedLinkError:
  Couldn't load /data/data/com.sample.teapot/lib/libTeapotNativeActivity.so: findLibrary returned null

It turns out there is a trick to have android give up more information about it. What you do, is load the library yourself in onCreate() of your native activity class. For this you use the System.load() call (and not the System.loadLibrary() call that the stackoverflow answer suggests.) Unfortunately, you need to know where your test device has actually placed the .so file, but if you do something like this:

public class TeapotNativeActivity extends NativeActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        System.load("/data/data/com.sample.teapot/lib/libTeapotNativeActivity.so");
        ...
You will get a proper error in the logs:
W/native-activity( 7426): onCreate
D/dalvikvm( 7426): Trying to load lib /data/data/com.sample.teapot/lib/libTeapotNativeActivity.so 0x410d97a8
W/dalvikvm( 7426): threadid=1: thread exiting with uncaught exception (group=0x40a741f8)
E/AndroidRuntime( 7426): FATAL EXCEPTION: main
E/AndroidRuntime( 7426): java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]:
  81 could not load needed library 'libGLESv3.so' for 'libTeapotNativeActivity.so' (load_library[1091]: Library 'libGLESv3.so' not found)

Hooray! Now we know which dependency is missing. Note that in this specific example, it is of course an issue of not specifying the ES3 requirement in the manifest. But this example is for illustration purposes only.

Originally, I was convinced that these errors were a case of not finding the library, because Android decided to append a "-1" or "-2" to the library name. But this was a red herring. The library is there all right. The thing is, it has dependencies that are not met, and are not reported when it fails loading.

By the way, to check if your library is really there, you could issue a command like:

$ adb shell run-as com.sample.teapot /system/bin/sh -c "ls\ -al\ /data/data/com.sample.teapot/lib/"
-rwxr-xr-x system   system     424232 2016-12-26 08:53 libTeapotNativeActivity.so

Thursday, November 24, 2016

Running a fast Android Emulator on Linux with kvm.

You can test your Android apps on an Android Virtual Device, instead on actual mobile hardware. If you emulate an ARM Android device, the performance will be low though. For faster emulation, it is better to emulate an x86 Android device.
Step 1
Make sure your Intel CPU is capable of virtualization, and go into your BIOS settings to make sure the virtualization feature of your CPU is enabled. You can also check from your command prompt by install cpu-checker package, and then run: sudo kvm-ok on the command line. You should see the report 'KVM acceleration can be used.'
Step 2
Install the correct parts of the Android SDK. Run on the command line: 'android' and install for your desired target (I use API level 19) install the Intel x86 Atom System Image.
Step 3
Start the AVD tool. On the command line, execute 'android avd' to open the tool.
Step 4
Select Create Device. Make sure to select Target: API level 19, and set the field CPU/ABI: Intel Atom (x86) as well. If you are using Google APIs, like Google Play Services, you should select the ABI: Google APIs Intel Atom (x86) instead. Don't forget to tick the Use Host GPU checkbox.

Step 5
Launch the virtual device by selecting 'Start' on the AVD tool.
Step 6
See if adb finds your virtual device with: 'adb devices' on the command line. Note the serial number for your device.
Step 7
Install your apk file using: adb -s emulator-5554 install bin/yourapp.apk
Enjoy the super fast emulation performance!
KNOWN ISSUES
If my app requests an OpenGL ES3 context, it fails:
E/EGL_emulation( 2463): tid 2476: eglCreateContext(919): error 0x3005 (EGL_BAD_CONFIG)

Final PRO-tip: Targeting API level 19 is your best bet, because running higher level APIs can cause crashes on older devices. To fix this, Google recommends actually shipping multiple APKs no less! Read more on this stackoverflow thread.

Sunday, November 20, 2016

Shallow Depth of Field in Little Crane.

A year ago or so, I added shallow depth of field rendering to my render engine for Little Crane 2. Because the details were getting vague, I had to refresh my mind. To do this, I've charted the flow of my render steps. I call them steps, not passes, because most of them involve rendering just four vertices for a full screen quad. The actual passes are a shadow-map generation pass over the models (not shown) followed by the standard render pass (step 0) that renders into an off screen buffer.


Step 1, 2, 3 and 4 all render into their own off screen buffer, and the final step 5 renders to the screen/window.

In step 1, the input image is copied but in the alpha channel, a Circle-of-Confusion size is stored. To calculate this size, the depth of the pixel is compared to the focal distance. This CoC size is a signed value which controls the blurriness. The value is 0.0 when it is perfectly in focus, it is -1 if it is in the foreground and requires maximum blur. When it is +1, it is also maximally blurred, but this time because it is in the far background. Intermediate results are for moderately blurred pixels.

In step 2, we simply down sample the input to half resolution (this increases blur sizes, and saves render cycles. Not shown is that it also contains the down sampled alpha channel with CoC values.

In step 3 and 4 we blur the input with 7 taps. First in a horizontal direction, and later in a vertical direction. This smears out the pixels over a 7x7 (49) pixel area with only 14 samples. The blur algorithm requires some thought though: the weights of the samples need to be adapted to the situation. This is because foreground pixels can be blurred over pixels that are in focus. But background pixels cannot be blurred over the in-focus pixels, because the blurred background is occluded by the objects in focus.

In step 5, we simply mix the blurred and the sharp versions of the image based on the circle-of-confusion value. If the pixel is in focus, no blurred pixels get mixed in. If the pixel is in the far back or in the far front, only the blurred pixel makes it to the screen, and the value of the sharp pixel is mixed out.

Wednesday, November 2, 2016

Cache Friendly

In my upcoming title Children of Orc the largest computational load is from the GOAP action planner that the NPCs use. I found that simple plans would be found in a millisecond. But larger plans would really tax the CPU. Especially if no plan exists to reach the goal state, a lot of cycles would be consumed. Typically a few seconds on a mid range corei5 CPU. This means it would be prohibitively expensive to do on a mobile device, if I were to port the game to iOS or Android.

I profiled it with linux command line tools, as well with Xcode's Instruments tool. Both showed that the cycles were spent in a linear search for the lowest cost node. The search would iterate though up to 32K nodes to find the lowest 'f' value in an array of these structures:


struct astarnode
{
        worldstate_t ws;                //!< The state of the world at this node.
        int g;                          //!< The cost so far.
        int h;                          //!< The heuristic for remaining cost (don't overestimate!)
        int f;                          //!< g+h combined.
        const char* actionname;         //!< How did we get to this node?
        worldstate_t parentws;          //!< Where did we come from?
};

Examining the assembly output of the linear search, I could not find anything wrong with the compiler's code. The only bothersome issue was that all the 'f' values that were being compared were lying 160 bytes apart.

To give the CPU cache an easier time, I decided to store the data as a structure of arrays instead. So now the search is performed on an array of ints, tightly packed, and no longer on an array of structures.

The result of this little exercise? A speed up of 2.7× which pleased me very much. If in the future, more speed ups would be required, I could possibly store the values in a priority queue instead. But for now, this will do nicely.

Note that in my GOAP implementation I search with A* and the most common operations are testing for presence in CLOSED and OPEN sets. These have already been accelerated with hash sets, shifting the bottleneck of the search to the finding of the lowest cost node.

Saturday, September 24, 2016

Debugging Software

I've always found Rob Pike's debugging story about Ken Thompson very powerful.

Ken would just stand and think, ignoring me and the code we'd just written. After a while I noticed a pattern: Ken would often understand the problem before I would, and would suddenly announce, "I know what's wrong." He was usually correct. -- Rob Pike.

This resonates with me, and I've always regarded debugging tools overrated. In many cases, you can do without those. My debugging method is typically a liberal use of assert() and fprintf(stderr,..) calls. But even those are not always a substitute of clear and deep thought, as I experienced again today.

Yesterday and today I was chasing a bug in my C code. The code generates topology and geometry of planets for my Children of Orc game. The visual and logical representations of the planet would not match up, and the Orcs would sink into the planet's surface. I spent a lot of time going over the code, over and over again. I even had a working Python version to compare with. But no matter how long I was staring at the code, I couldn't find the culprit.*)

I eventually solved the issue far away from the keyboard, when at the play ground with my toddler son. Just forming a mental picture of the processes, and some deep thinking on what could cause the observed behaviour of the code. It turned out to be a case of miss-used vertex indices. I keep two versions of the planet mesh, one where the polygons share vertices via indexing. The other where polygons are flattened out, and do not share vertices. I was using the indices of the former one to index the mesh of the latter. Going over the code, adding printf statements, did little good. Stepping away from the keyboard helped a lot. When back home again, finding and fixing the bug took seconds.

I also learned that in this case, the C code was double the size of the Python code. Before I ported it, my estimate was that C would require almost 10 times the lines of code. Even though Python is much more concise and powerful than the low level C, in this case it came down to a factor 2.

*) Comparing the outputs of Python and C versions was of little use, as both versions used different Simplex-Noise implementations. Also, the output was binary, not ascii. This made it hard to understand what specific part of the data was incorrect.

Friday, September 23, 2016

New Game: Children of Orc.

I have just introduced my new game to the world. It is called Children of Orc.

Children of Orc is a real-time third-person strategy game that is set on a procedurally generated hex-planet. Check out the trailer video:

To get published on Steam, it can use a little help with green light votes.

Tuesday, September 20, 2016

Blender Gotchas

There are many nooks and crannies in Blender that can catch you off guard. Here I will document them for reference by my future self, lest I would forget.

By default, Blender uses CPU, to use GPU on Linux, you have to, once as root, start blender -> User Preferences -> System -> Cuda. Quit blender, and then start as regular user, and do the same. Then select Cycles renderer, and under Render properties, Device: GPU Compute.

By default, Blender add ambient light. Why would you if you do Path Tracing? So disable it with: Properties World -> Surface Color black.

By default, Blender does not generate transparent PNGs. Render properties -> Film -> Transparent.

For high quality rendering with less noise, Render properties -> Sampling -> Samples Render: 100+

When importing let's say Wave front OBJ, the colour space is presumed linear, for vertex colours. This typically is not the case in OBJ files, so you need to fix those. Use this script. Extract the .py file and paste that in a text panel, then run the script.

Friday, April 15, 2016

Imhotep Progress - WEEK 06

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

The game is finished and we have a release data! On May 6th, 2016, Imhotep, Pyramid Builder will launch on Steam.

This week, I added stack frame capture on crashes. I tuned the game. I added a difficulty settings BABY/NORMAL/LEGEND. I added a window icon. And I added price labels for the building types.

A big thank you to the people helping me do the beta test. There is still room to get into the beta test if you want. Just drop me an email if you want to help out.

Saturday, April 9, 2016

Imhotep Progress - WEEK 05

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

Getting real close to a ship-able product now. As a matter of fact, the first play tester is now playing it, and finding bugs. For the first time, someone else than myself or my little 5 yo girl is playing the game.

Added cats to the game! They follow around humans, and sit and observe every now and then. When you pick them up, they meow!

I added file versioning for saved games. I now adapt the game speed to the display speed, so that running on a 144Hz gamer panel will work properly. I fixed some delta-time inaccuracies, as I was storing game time in a 32bit float, not a double precision float! I wrote a blog posting on why you should use a 4⅙ ms simulation time step.

If you are interested in helping out play testing, send me an email and I will give you a Steam code. Currently I have windows64 and linux64 binaries. OSX64 will be added at some time.

Saturday, April 2, 2016

Imhotep Progress - WEEK 04

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

I added the restocking of the building stones if a user stops the build at a cell. Improved the initial spawn so that all four characters are visible. Added menu highlighting. Hooked up leader boards for fastest build, largest population, and most silver. Implemented button highlighting. Moved save files to steam directory. I ported the game from Linux to Windows using visual Studio. Upgraded to latest steam API. Auto load on launch, and auto save on exit. Fixed the OSX build. And lastly, I modelled a cat, because my good friend Matt told me a game on ancient Egypt needs cats in it.

Wednesday, March 30, 2016

Visual Studio gotchas

Every time that I try to develop for windows (with Visual Studio), I have a hard time. And I do this so infrequently, that I tend to forget stuff too. I now try to make a windows version of Imhotep, Pyramid Builder. Here I will document some gotchas when developing under windows.

  • It turns out that for 64bit builds that use libSDL2, you need to add some inputs to the linker, being: winmm.lib, Imm32.lib, version.lib libraries.
  • What's up with the '32' suffix for 64 bit builds? Somehow you still need to link Imm32 and OpenGL32 and not Imm64 or OpenGL64?
  • The best way to generate new project files is to copy them from an old project, and edit the XML contents.
  • Don't use a full screen app and a full screen debugger at the same time. If you hit a breakpoint, the apps fight over the screen, and you cannot control the debugger any more.
  • Win32 builds cannot handle functions that take four __m256 arguments. Three is fine, but for the fourth, the compiler craps out with the message "formal parameter with requested alignment of 32 won't be aligned."
  • If my code were to be C++ I could replace with const references to __m256, but this is C code. So I have decided to not build 32bit versions of my game at all.
  • To get rid of the generated .iobj and .ipdb files, change the Linker/Optimization/Link Time Code Generation option to something other than /LTCG:Incremental.
  • Before creating my .exe file, Visual Studio creates a .lib and .exp by the same name. I don't know why. Configuration is set to Application(.exe) so why create the lib?

Friday, March 25, 2016

Imhotep Progress - WEEK 03

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

Good progress was made this week, again.

I added ixes for the serialization of game state.

I improved the huts, which are now replaced by larger tents that house 10 workers, instead of the 6 in the old huts. These tents have better collision characteristics too, as the workers have less issues path planning around them.

Hooked up Remotery to find out the cause for a slow down. I have not been able to catch the issue yet, though.

Added steam leader board for the fastest pyramid build.

And the biggest new feature: player-designed pyramids! The player now directs the building of the pyramid by marking out the spots on the terrain where blocks need to be deposited. You can also use this feature to build new roadways, and ramps up steep cliffs to create short-cuts for your workers.

Tuned the path planning. The workers are now less averse to climbing slopes. Steep paths are still avoided, but less so. This fixed an issue where the workers could get stuck in a vortex of the path planning flow.

Friday, March 18, 2016

Imhotep Progress - WEEK 02

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

Lots and lots of progress this week. I added the capability for the player to pick up and drop individual members of the crowd, which at the moment also comes handy when a worker gets stuck during navigation. Added spawning from multiple tax offices. Implemented win/lose conditions: you lose when half your population is dead. You win when the pyramid is finished.

I added steam stats and steam achievements. Currently I have these:

I also added two great music tracks, one for menu music, one for in-game music. Both pieces have a distinct North African vibe to it. So it helps you get into the mood of the Egyptian lands. I must say that adding music to a game prototype does add some legitimacy to the game, and makes it feel more like a complete product.

I've added save/load game functionality. This was a hard one, as I need to track down each little piece of game state, and make sure it stores and restores correctly. It is implemented now, but I'm not sure it's without bugs yet.

And to conclude: I also added sound effects. They are pretty neat. You can hear the workers pickup water, drop water, harvest, drop grain, pickup and drop food, pickup and drop stones. With proper 3D audio using OpenAL. If you zoom out, you hear all the action in the distance. And zoomed in, you hear specific actions.

Saturday, March 12, 2016

Imhotep Progress - WEEK 01

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

This week has been spent on getting actual game play in. I hooked up the spending of silver on buildings. Here's the hieroglyph that spells silver.

I added scrolling by moving the mouse to the edge of the window. I fixed the OSX build of the game. It looks really nice and sharp on a retina screen. I added emoticons. If a builder is tired and hungry, a sleepy face is used to denote that state.

I created a hiring menu. Once hired, the new workers are spawned sequentially from the tax office. I improved the gradient visualization.

The buildings all compete with each other for deliveries of goods. They also compete with each other in providing goods for pickup. This competition needs to be regulated, as we do not want to swamp or starve one building over the others. To do this, I am using the notion of 'urgency'. I've spent a lot of time this week tuning these urgency levels, so that if a building goes too long without service, it will increase the desirability to the workers.

All these efforts mean that the game has slowly gotten to a playable state. Placing buildings, hiring workers, earning silver are all in, so there already is a game challenge in there. It just needs a lot of finishing up. Win/lose conditions, leader boards, achievements, load and save games, game settings and Steam integration are all still on the todo list. Hopefully I can take some of these on next week.

Friday, March 4, 2016

Imhotep Progress - WEEK 00

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

This week, the green light was given for publication, and in this week I made the following progress:

I've introduced the concept of both 'Silver' and 'Tax Collector' to the game. So far, silver only has a hieroglyph statistics title. For the Tax Collector, I made a hieroglyph, I designed a 3D model of a building with a guard using Wings3D. I generated a lightmap for this building using Blender.

The idea of the tax collector is that the food that is produced is either delivered to huts for consumption by the workers, or it is delivered to the tax collectors. When the latter happens, silver money is generated and added to the player's purse. I want to use this silver to finance new buildings, and hire new workers. The idea is that the player starts with one hut, one field, one bakery and one tax collector's office. In addition to this, the player starts with a few workers as well. To build up the work force, taxes need to be collected and spent.

I have also added panning with cursor keys (in addition to panning with mouse drag which had already implemented.) I intend to add panning by moving the mouse cursor to the edge of the screen as well, like Cities: Skylines does.

I've also added basic tooltips on the mouse that translates the hieroglyphs into English. I want to switch these off by default, to add to the mystique of the game. Figuring out the hieroglyphs should be part of the challenge, I think. I will add a cheater mode for the lazy people.

Wednesday, March 2, 2016

htr sr

So these hieroglyphs (in this case, read from right to left) spells htr sr. We only know the consonants of the Ancient Egyptians, and the scholars do not know what vowels were in their words. This 'htr sr' translates to Tax Official in English.

The twisted wick is the 'h' sound, the bread loaf is the 't' sound, the mouth is the 'r' sound and the folded cloth is the 's' sound. The man with staff at the end is a determinative, clarifying that it pertains to a person.

Why do I know this? Because my game Imhotep, Pyramid Builder uses a hieroglyphic UI, and I needed to add taxes to my game.

There are some great resources available online to translate into hieroglyphics. There is the book by Charles E. Nichols. And there is this online dictionary. Wikipedia's Gardiner's sign list is of big help too. There are plenty of ancient samples available too. And a quick introduction to transliteration as well.

To create the artwork for my UI, I study a few samples from the antiquities for each symbol. Then I create my own version of it in Inkscape, the SVG editor. I export them to PNG, and convert them to raw images for use in my game.

I am seriously considering not showing the English translation of the UI, by default. So that figuring out the UI becomes part of the challenge. I would add a cheater-mode for lazy people, which enables tooltips with mouse-over so that they know the English meaning immediately.

So yeah, however the game turns out, it is bound to be unique. I don't think there are any other games with a hieroglyphic UI. The game would also stand out on the massive crowd simulator that I implemented for it. Thousands of little workers, each going about their own business. This is courtesy of the Continuum Crowds algorithm, that enables path planing for massive crowds. I partition my crowds in many flow-fields, depending on their current needs (fetch water, deliver food, pick up sandstone, etc.) And the little workers will plan their journeys, based on congestion, preferring to walk with the dominant flow of traffic, not against it, and such. It is quite pleasing to the eye when large crowds are moving. This game is coming to steam in 2016.

Saturday, February 27, 2016

Imhotep, Pyramid Builder coming to steam

So, my game Imhotep, Pyramid Builder has been given the green light for publication on Steam. This would make it my second published game for the Steam network. So starting next week, expect a weekly progress report. I found this helped me a lot to bring Little Crane to the Steam market in the shortest possible time.

I will probably overhaul the game mechanic, and make it more like a traditional strategy/building game. Currently it is a build first, and then press PLAY non-interactive simulation. But I will move away from that. I think I will put the price point much lower than I used for Little Crane, Steam edition.

The visuals look a little better now, as I have added light maps. The light maps are static, and computed with the Blender Cycles renderer.

I think a Pyramid Building sim is a world's first. If you know of an earlier title, let me know! Also, the massive scale of the crowd may not be unique, it must at least be incredibly rare. I know of no game title that simulates thousands of people without pausing simulation for off-screen actors. The current implementation requires a CPU with AVX SIMD support, and OpenGL3.2 Core Profile support.

Wednesday, January 27, 2016

Baking Lights using Blender

With Blender you can bake the lights using the Cycles renderer onto light maps. For static geometry, you can get some really nice lighting with diffuse bounces for your models. This posting roughly describes how to achieve this.

Baking requires quite a bit of computational power. It's best to do this on the GPU if you have a fast GPU. If you have an nVidia card, you can use OpenCL to accelerate these computations. Some caveats here: Don't use Ubuntu's blender package: it does not come with OpenCL support. Instead download Blender directly from the Blender site. Next, there is this really quirky bug: Blender cannot find the OpenCL devices if you do not first run a session as root. As root, start blender, then in User Preferences / System, set the render device to OpenCL. Then change the Renderer to Cycles Renderer, and render the cube. Now you can quit Blender and restart it again as a normal user.

Open a new project, go to User Preferences and choose the OpenCL device. Then set the Renderer to 'Cycles Renderer' at the top of the screen. Import the geometry you want process. I find it best to split the geometry per material.

Add some light to your scene. I find that an inverted hemi sphere works fine. Create a new material for this sphere, and make it Emissive (Use Nodes) and you can see the material in the Node Editor. If you want to avoid Light Fall Off, you can add a Light FallOff node, and feed it into the 'strength' with the Constant output.

For each object, Blender will probably have created its own material. Click on 'Use Nodes.' You need to add an unconnected Texture node to the Node View for each material, and give it a newly created texture.

For each of the objects do the following: select it in the 3D view, then go to Edit Mode. When in Edit Mode, under Mesh menu, choose UV Smart Unwrap. Select a small spacing (e.g 0.03).

In the Properties view, select Render, and then set the renderer to GPU computation.

In the Properties view, select Render, and open the Sampling section. You need to increase the sample count to something suitable. You can check the quality by executing a render with F12.

Now in the 3D view, use Object Mode, to select all objects.

In the Properties / Render menu, select Bake to bake out to all light maps attached to the selected objects. You can select what light to bake. I use Combined, but if you want, you can bake Diffuse Indirect only.

After the baking, change the 3D view to the UV Image view, and see what the light maps look like. To see the light maps applied, you can set the 3D View viewing mode from Solid to Textured.

Each Light Map needs to be saved to disk. View it in the UV Image view, and then press F3 and save it out as PNG some where.

Lastly, do not forget to save the blender project, and export the model again, I use Wavefront OBJ, so that the UV coordinates for the lightmaps get saved. You can use the Wings3D editor to see the results. For this, add Ambient light, and set all materials to Ambient 1,1,1,1 and Diffuse 0,0,0,0.

Monday, January 25, 2016

Screen Space to Object Space in OpenGL.

Something I learned today: if you want to pick a 3D object from mouse coordinates, you can go from screen space coordinates to object space but you need to pay attention to the normalization of the screen space coordinates.

First, to get the screen space coordinate, you can use the mouse location x,y normalized on ( -1..1, -1..1 ) range. You need to supplement this with a z-coordinate that you get from the depth buffer.

glReadPixels( scrx, scry, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);

Where I initially went wrong is, not realizing that this z coordinate needs to be remapped as well, from a 0..1 to a -1..1 range. The hint that lead me to this was looking at this code.

All you then need to do is multiply a matrix with this screen space coordinate to get a model space coordinate. The matrix to multiply is of course the inverse of the model-view-projection matrix. Simple enough to do yourself, so you do not need to link to libGLU just for its gluUnproject() function.

Oh, and do not forget to divide the x,y,z of the multiplication result by its w component.

Friday, January 1, 2016

2015 totals

So, The Little Crane That Could on iOS is straining up hill, but still going. On Android it seems to have caught a second wind. Here are the 2015 results (Number of free Downloads.)

2015 2014 2013 2012 2011
iOS 630K 1300K 3199K 3454K 1550K
Android 1525K 825K 1579K 1656K -
Mac 20K 30K 53K 81K -
OUYA 0K 4K 15K - -
Kindle 52K 46K 95K - -
Rasp Pi ? ? 6K - -

This is the first year that Android downloads bested the iOS download numbers. And by a big margin too. Much of that is to attribute to a feature that the Google Play team did on Little Crane earlier this year.

This adds another 2.2M, totalling a 16.1M lifetime downloads. Hooray for Little Crane!

This was also the year that Little Crane saw its successor release: `The Little Crane That Could² : Mud Play' as it was called on iOS, and as `Little Crane' on Steam. In hindsight, this dual naming was too confusing. Also, it's adoption rate in the market has been modest: 60K free downloads on iOS, and 1383 paid downloads on Steam.