Humble weekly bundle includes source code to Uplink, Darwinia and DEFCON

8. August 2013

 

This is a kinda cool opportunity, this weeks Humble Indie Bundle actually includes the source code to many of the games included.

image

 

Four games plus tons of extra content. The Humble Weekly Sale features a new deal every Thursday. Be sure to jump on this amazing offer before it’s gone! This week, pay what you want for Uplink, Darwinia, Multiwinia: Survival of the Flattest, DEFCON, Voxel Tech Demo, City Generator Tech Demo, and source code access to Uplink, Darwinia, Multiwinia: Survival of the Flattest, and DEFCON. Plus you'll receive a never-before-heard story of Introversion from the studio's founders Mark and Chris. If you pay $19.99 or more in the first 24 hours of this weekly sale, you’ll also receive early access to Prison Architect and the full game upon its release, DRM-free and on Steam for Windows, Mac, and Linux! After the first 24 hours, you can still get Prison Architect with a purchase of $24.99 or more!

 

Fire it up DRM-free and cross-platform. Your purchase will get you four wonderful games DRM-free and on Steam for Windows, Mac, and Linux as well as two tech demos DRM-free for Windows. Pre-ordering Prison Architect will get you instant access to the alpha and the completed game DRM-free and on Steam for Windows, Mac, and Linux when it is finished as well as the early access game! Full system requirements for the games can be found here.

 

Pay what you want. Pay anything you want to receive four amazing games, two tech demos, and source code access. Pay $1 or more to receive Steam keys. Pay $19.99 or more within the first 24 hours of this sale and $24.99 afterwards to get Prison Architect!

 

Support vital charities. Choose how your purchase is divided: between Introversion Software, the Child’s Play Charity, or the Electronic Frontier Foundation. And, if you like this weekly sale, a tip to Humble Bundle would be greatly appreciated!

 

From what I can tell, at least for Uplink, the source code is written in C++.  Introversion previously offered the Uplink Developer CD.  What however is absent is the license it is being released under.  Be careful there, I am always hesitant accessing source code to a license that isn’t strongly defined.  Don’t want to end up on the wrong end of a nasty lawsuit because your game is similar to one of these titles and you peeked at the source.  I’m sorta surprised the license isn’t part of the release information.

I actually believe I own all of these games many times over as it is.  Until I hear terms of the code license, I’m staying away.

 

EDIT:

Thanks to @DarkCisum on Twitter, I have links to the licenses released that prior code releases used, it’s a fairly safe assumption the licensing remains the same.

Defcon License

Darwinia License

Uplink License

 

Wearing my IANL ( I am not a lawyer ) hat, I don’t see anything too scary, but also find the license a bit too vague for my personal comfort.

News ,




C++ memory management isn't the boogie man you may think it is

2. April 2013

I hear over and over again in programmer forums, mostly beginner forums, that C++ is hard because you have to manually manage memory!  This is not only wrong, it's dangerous.  Whenever you see this comment, be wary about following this persons advice in the future. Why?  Simply put, because if you are manually managing memory in C++, you are probably doing it wrong.  We will look at why in a moment.

 

Secondary to the fact you really shouldn't be manually managing memory all that often in C++, even if you have to, it shouldn't really be all that hard.  Memory management in C++ doesn't make the language hard, it makes it fragile, their is a big difference.  The concepts behind memory management really aren't rocket science, it's the kind of thing you can learn in an afternoon.  However, screwing it up can easily introduce a bug into your application or cause it to outright crash.  This is what I mean by fragile.

 

So in this post we are going to start with why you shouldn't be managing memory manually, show you how you actually go about doing this, then finally for those times you absolutely have to, show you the ins and out of basic C++ memory management.  One thing I should point out right away is many of the things I discuss in this article didn't exist until somewhat recently (such as smart pointers).  Languages evolve, C++ certainly has.  I assume you are using a reasonably current complier, if you aren't, much of what we discuss may not be applicable to you.

 

Before we can go too far, there are a few concepts you need to understand.  When working in C++, there are three kinds of memory you need to be aware of.

 

The Stack, the Heap and all the other kinds we are going to pretend don't exist.

 

First we will talk about the types we won't talk about.  In this discussion I am oversimplifying things slightly to focus on the stuff that is most relevant 99% of the time.  There are other kinds of memory ( globals, statics, registers, etc… ), but until you need to know about them, you can safely ignore them.

 

That leads us back to the stack and the heap.  Let's start with the stack...

 

The Stack

The stack is well named, think about a stack of plates at a cafeteria, and you have the basic idea of what the stack is like.  

StackOfPlates

Each time you create a variable on the stack, think of it like adding a plate to the top of this pile.  When a variable goes out of scope, think of it like removing a plate from the pile.

 

Let's look at it with actual code.

#include <iostream>

 

void SomeFunction(int a2, int b2)

{

    int c=3;

    int d=4;

    std::cout << a2+b2+c+d;

}

 

int main(int argc, const char * argv[])

{

 

    int a = 1;

    int b = 2;

    SomeFunction(a,b);

}

 

This simple program creates a pair of values a and b and passes their values to the function SomeFunction() which then creates two more variables c and d and adds them all together, printing out the total.

 

So, what is happening here on the stack?  Look at the following diagram and think in terms of the stack of plates (bowls?) above:

 

Stack

 

As this code runs, first a is added to the stack, then b.

Next copies of a and b are sent as parameters to our function, resulting in a2 and b2 being added to the stack.  This is an important concept to grasp.  When you pass a standard variable by value, it's actually only the value that is used, a new variable is created for each parameter.

Then within our function, c and d are created (on the stack) as well.

 

Now is when the stack starts to make sense…  when things are deallocated.  See, the stack is very aware of scope and when a variable will die.  At the end of our function, d, c, b2 and a2 all go out of scope, so they are removed from the stack, like grabbing plates from the top of a plate stack.

After our function call, our stack will look like:

Stack2

Then finally our program execution ends, and b and a will be popped from the stack as well.

 

The nice thing about the stack is, the program knows when a stack variable is no longer needed ( when it goes out of scope ) and gets rid of it for you.  In my initial revision of this post, I made the stack sound like a bad place to create your variables and this is very much NOT the case.  In fact, unless you have a very good reason ( see the following paragraph ), you should always favour allocating on the stack, it's a heck of a lot less error prone and often quicker.

 

The downside to the stack are two fold.  First, it has a limited size… depending on your platform and your compiler settings, ranging from KB to a couple of MB in size.  I believe Visual C++ 2010 on Windows creates a default stack of 1MB.  Next, sometimes you want variables to outlive the scope they are declared in… quite often actually, such as a function that allocates a big chunk of memory to big to efficiently return by value ( and thus creating a copy ).  In this case you need...

 

The Heap

 

The heap is nothing special, don't confuse it with the data structure "heap", they have nothing to do with each other.  This "heap" in question is simply slang English… like you might say you have "a heap of clothing", you have a "heap of memory".  It's simply a big pool of memory available for your application.  Unlike the stack, which is very ordered and organized, the heap is just a gigantic blob of memory.

Now, the bright side to the heap is… theres lots of it.  As much memory as your system contains… in fact, probably much more thanks to virtualization.  When we are talking about manual memory management, it's the heap that we are talking about.

So, how do you create memory and destroy memory on the heap?  This is where new and delete come in.

Consider this super contrived example:

#include <iostream>

 

void FillBuffer(char * buffer)

{

    for(int i = 0;i < 10000000;i++)

        buffer[i] = 'A';

}

 

int main(int argc, const char * argv[])

{

    char * buf = new char[10000000];

    FillBuffer(buf);

    delete [] buf;

}

 

Here we create our variable buf on the heap, this is obvious from the use of new.  It is then passed into the function FillBuffer, which fills it with the character A.  Finally it is deleted.  There are a few things of note here, two showing the advantages of the heap, and one potential hand grenade.

First this code allowed us to make a 10MB data structure, you simply couldn't do this on the stack.  If you want to see first hand, try running the following code on your computer:

 

#include <iostream>

 

int main(int argc, const char * argv[])

{

    char buf[10000000];

    for(int i =0;i< 10000000;i++)

        buf[i] = 'A';

}

 

On MacOS, you get EXC_BAD_ACCESS errors as a result, and that makes sense, as you are trying to allocate more memory ( on the stack… new wasn't used ) than is available.  So, obviously if you have a large amount of data, it has to be on the heap.

The other major advantage to the above code is when you call FillBuffer, only a pointer to the data is passed ( 4bytes in size on 32bit Windows, 8bytes in size on 64bit ) instead of creating a 10MB copy.  If this concept doesn't make a lot of sense right now, bear with me, I will explain what a pointer actually is in a bit more detail shortly.

 

So, what then is the problem with direct memory management?  Well, remember this line:

delete [] buf;

Had I accidentally printed:

delete buf;

We would have just leaked 10 MB of memory!  If you don't manually release(delete) the memory you allocate using a pointer, when the pointer goes out of scope, that memory is lost. In this contrived example, its easy enough to remember a delete for every new, but in a real application, it's a very simple mistake to make, as is forgetting to include [] when dealing with an array of values!  It's even easier to leak memory when an exception occurs, causing your program to not necessarily run in the order you expected it to.


One thing to keep in mind here, I said earlier that if exists on the Heap, it was allocated with new.  This is true but somewhat misleading.  For example, when you use many of the standard C++ data structures, such as std::vector, even though you may create the object on the stack internally it is still allocating memory on the heap for it's own data.  It is just taking care of most of the heavy lifting for you.

 

So, thats a quick view of the stack, the heap and how memory works…  now I want you to forget it all!

 

As a new to C++ developer, every single time you find yourself typing new or delete, it should raise an alarm bell of sorts!  Don't get me wrong, there are reasons to use both, but they should be few and far between.  What then is the alternative?

 

Resource Acquisition is Initialization (RAII)

That sound scary?  Don't worry, its nowhere near as bad as it sounds.  RAII is a term/idiom coined by C++'s creator Bjarne Stroustrup.  I'll go with the Wikipedia description:

In this language, the only code that can be guaranteed to be executed after an exception is thrown are the destructors of objects residing on the stack. Resource management therefore needs to be tied to the lifespan of suitable objects in order to gain automatic allocation and reclamation. Resources are acquired during initialization, when there is no chance of them being used before they are available, and released with the destruction of the same objects, which is guaranteed to take place even in case of errors.

Again, this sounds much scarier than it really is.  The part that you need to really pay attention to is this one: needs to be tied to the lifespan of suitable objects in order to gain automatic allocation and reclamation.

Remember earlier how I said objects on the stack are automatically disposed when they go out of scope, while new'ed objects on the heap aren't, and if not manually deleted, will result in a leak?  Well, thats where smart pointers come in.  Esentially a smart pointer is a variable created on the stack, that creates the heap memory for you.  However, when it goes out of scope, it's destructor will be called and the resources it manages will then be disposed.  Let's take a look at our previous example, just using a smart pointer instead.

#include <memory>

 

void FillBuffer(std::unique_ptr<char[]> & buffer)

{

    for(int i = 0;i < 10000000;i++)

        buffer[i] = 'A';

}

 

int main(int argc, const char * argv[])

{

    std::unique_ptr<char[]> buf(new char[10000000]);

    FillBuffer(buf);

}

 

 

I will be the first to admit that the syntax of a smart pointer isn't the most beautiful thing in the world, but it has many advantages.  The first and most obvious… notice we no longer delete the pointer?  Don't worry, this doesn't result in a memory leak, this is RAII in action.  See what's happening here is, std::unique_ptr lives on the stack and full fills a pretty simple function.  On creation, it allocates your memory.  When it's destructor is called, it de-allocates your memory.  Since the destructor is guaranteed to be called if an exception occurs, there is no fancy error handling required here, and since the unique_ptr lives on the stack, it will be destroyed ( and thus the memory it holds ) when it goes out of scope.

The second less obvious thing here, notice as a parameter to FillBuffer, our pointer is based by reference? ( & ).  This is a by product of the unique_ptr.  Just like Highlanders, there can be only one.  unique_ptr's will prevent copies of the pointer from being made.  Sometimes this is desired behaviour, but sometimes you want to have multiple pointers to the same object.  In that case you can used std::shared_ptr.  Shared pointers work a bit differently, the allow multiple different pointers to point to the same thing and keep a reference count of the number of things pointing at your object.  Each time one is destroyed, the reference count is reduced, if the reference count hits zero, the memory is freed.  unique_ptr and shared_ptr both perform different functions, but both work to make memory management more controlled, more predictable and less fragile.  Once you get over the syntax, they actually result in a lot less work too, as your error handling is greatly simplified, you don't have to watch memory usage so closely, etc...

TL;DR version.  Smart pointers essentially wrap your heap based memory allocation in a stack based object.  This objects creation and destruction manage the lifecycle of your memory, simplifying error handling and making memory leaks a great deal less likely.

 

A small primer of C++ style memory management

It's possible at this point that you have very little prior experience with memory management at all, so to understand why something is better, it can prove handy to understand the way that is worse.  It's also quite possible that the idea of a pointer is completely alien to you, so let's have a quick primer of what a pointer is and how it works.

Let's look at a very simple program:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int * i = new int();

    *i = 42;

    std::cout << *i;

    delete i;

}

Here we are creating a pointer i that points to type int.

This is an important concept to get your head around.  A pointer is NOT the same type as what it points to.  I will explain this more in a moment, for now let's carry on.

You declare a pointer type using the asterix '*' operator.  As we saw earlier on, to allocate memory on the heap you use the new operator, therefore the line:

    int * i = new int();

Creates a pointer to type int named i and allocates space for an int on the heap using new.

Somewhat confusingly, the * operator is also used to access the data a pointer points to.  One important thing to keep in mind, a pointer is ultimately a location in memory.  On a 32 bit system there are 4,294,967,295 bytes (2^32) of memory and a pointer is simply the location of one of those bytes.  If it helps, you can simply think of pointers as bookmarked locations in memory.  To actually read what is at the location, you "dereference" it, which is where the * operator comes in.  So the line:

*i = 42;

Is saying, at the memory location pointed to by i, write the value 42.  Since we told the compiler what type of data our pointer points to, it knows how to do the rest.  Again, you dereference a pointer to read it's contents too, like we do when printing it out cout.  Once again, the compiler knows what the memory pointed to contains because it knows what type of data the pointer points to.

 

Let's go back in time a moment, remember when I said a pointer is not the same type as what it points to… this is very important to realize.  If you say 

    char * c = new char();

Just like before, you are creating a pointer to type char NOT a char.  This little sample might make the difference a bit more clear.

#include <iostream>

 

int main(int argc, const char * argv[])

{

    char c = 'A';

    int i = 42;

    

    char * ptrC = new char();

    *ptrC = 'A';

    int * ptrI = new int();

    *ptrI = 42;

    

    

    std::cout << "char c has value of " << c << " is located at " << static_cast<void*>(&c) << " and is " << sizeof(c) << " bytes" << std::endl;

    

    std::cout << "int i has value of " << i << " is located at " << static_cast<void*>(&i) << " and is " << sizeof(i) << " bytes" << std::endl;

    

    std::cout << "char ptrC has value of " << *ptrC << " is located at " << static_cast<void*>(ptrC) << " and is " << sizeof(ptrC) << " bytes" << std::endl;

    

    std::cout << "int ptrI has value of " << *ptrI << " is located at " << static_cast<void*>(ptrI) << " and is " << sizeof(ptrI) << " bytes" << std::endl;

}

 

(And yes, this example leaks memory).

Here is the results of running this application on 64bit Mac OSX, if you are on a 32bit OS, your results will be slightly different.

char c has value of A is located at 0x7fff5fbff8bf and is 1 bytes

int i has value of 42 is located at 0x7fff5fbff8b8 and is 4 bytes

char ptrC has value of A is located at 0x1001000e0 and is 8 bytes

int ptrI has value of 42 is located at 0x100103a60 and is 8 bytes


As you can see, both of our pointers are 8 bytes ( 64bit OS, 2^64 == 8 bytes ), even though the data they point to is substantially smaller.  In the case of a char pointer, the pointer is actually 8 times larger than the data it points to!  As I mentioned earlier, each pointer is actually just a location in memory.  That is what the 0x____________ represents.  This is a 64 bit address in hexadecimal form.

One other thing you might have noticed is even standard data types have a memory address, you can access the location of a variable in memory using the address of operator ( & ).  This makes the following possible:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int i = 42;

    int *pointerToI = & i;

    std::cout << "The answer to the meaning of life is "  << *pointerToI << std::endl;

 

    if(pointerToI == &i)

    {

        std::cout << "Memory locations are the same" << std::endl;

    }

}

 

Which will print:

The answer to the meaning of life is 42

Memory locations are the same


You need to be careful with ownership here, there are a number of potential pitfalls. If you point to a stack variable that goes out of scope, you are in for a world full of hurt, consider:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int * meaningOfLife = NULL;

    {

        int i = 42;

        meaningOfLife = &i;

    }

    std::cout << *meaningOfLife << std::endl;

}

 

The problem here is, meaningOfLife is now pointing at a memory address that is no longer valid.  i ceased to be when it went out of scope.  Now the most insidious part… if you run the above code, it will work and appear to display proper results.  Just because a location in memory is no longer valid, doesn't mean it doesn't still hold the correct data, memory isn't blanked when it is released.  This means your pointer will appear to work properly… until something reuses that address, then KABOOM!

 

 

Pointers to Pointers

Let's take a look at one more common hang up with C++ memory management, pointers to pointers.  We are getting awfully close to an inception moment here.  Consider:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int ** pointerToPointerToInt;

    

    int * pointerToInt = new int(42);

    pointerToPointerToInt = &pointerToInt;

    

    std::cout << **pointerToPointerToInt << std::endl;

    

    int * pointerToDifferentInt = new int(43);

    *pointerToPointerToInt = pointerToDifferentInt;

    

    std::cout << **pointerToPointerToInt << std::endl;

}

 

As you can see, you can actually have pointers to pointers, this is done using multiple * operators.  In fact, you can have pointers to pointers to pointers to pointers if you really wanted to, and that would use ****.

Otherwise, a pointer to a pointer works almost identically to a normal pointer.  The only difference is, when you dereference a pointer to a pointer using the * operator, you are left with an ordinary pointer.  You have to dereference it twice to get what it is pointing at.  In the above example, when we wanted to change the pointer our pointerPointer pointed at, we dereferenced it a single time, but when we wanted to access the actual value pointed at, we dereferenced it twice.  Pointers to pointers aren't actually all that uncommon, a linked list is often implemented this way… fortunately the logic is consistent.

 

The Array… think of it as another pointer...

On last thing to touch on… the array.  You may recall earlier when we created our char buffer, we actually did it using the array operator.  At the end of the day, an array is mostly just trickery over a continuous block of memory.  When you say:

char alphabet[24];

You are actually saying "give me a block of memory 24 chars long".  So pointers are arrays can do some rather neat things...

#include <iostream>

 

int main(int argc, const char * argv[])

{

    const char alphabet[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',

        'Q','R','S','T','U','V','W','X','Y','Z' };

    

    const char * letter = &alphabet[0];

    std::cout << *letter << std::endl;

    

    for(int i = 0; i < 26; i++)

        std::cout << *(letter++);

    

    letter = &alphabet[0];

    

    std::cout << std::endl << letter[5] << std::endl;

}

 

Run this code and we will see:

A

ABCDEFGHIJKLMNOPQRSTUVWXYZ

F

 

For the record, almost everything you see above IS A VERY BAD IDEA!  This is the kind of code we are trying to avoid, as it is horrifically fragile, but lets take a look at what we are doing here...

First we create a const char array holding the characters of our alphabet.  You cannot take the location of an array...

&alphabet;

An array is just a chunk of memory, if you want it's "location" you actually take the location of the first item in the array, that is exactly what:

const char * letter = &alphabet[0];

Does, this creates a pointer to type char and points it at the first character in our alphabet array.  As you can see, when we print it out we get A as expected.

Next we loop through the letters of alphabet printing our dereferenced pointer value.  You may notice each iteration we ++ our pointer… welcome to pointer arithmetic.  Remember before when I said a pointer was simply a location in memory, and an array was a continuous block of memory, well, you can iterate between pointer items using arithmetic.  The line:

(letter++)

Is functionally the same as

letter = letter + sizeof(char);

 

You may notice later on, we access our pointer like it was an array, when we called:

    std::cout << std::endl << letter[5] << std::endl;

The array subscript operator ( [ ] ) is functionally equivalent to doing the following

    std::cout << std::endl << letter[5 * sizeof(char)] << std::endl;

Be very with pointer arithmetic and using the subscript operator though, as there are absolutely no bounds checking done, so there is nothing to prevent you from trying to access a location that doesn't exist.

 

Hey, wait a minute here!!!

You may have noticed we use the * operator to both declare and dereference pointers.  We also use the & operator to both declare a reference as well as to get the address of a variable…  how does that work?

 

Well, it's all about context.  When declaring a variable or defining parameters, * indicates a pointer while & indicates a reference.  However, in all other scenarios, the operators have their alternate meaning.  I personally think this was a bit of a mistake for clarity reasons.

 

Conclusion 

Ok… so maybe it isn't EASY per say, but memory allocation in C++ isn't the black magic it is made out to be.  Especially because, 99% of the time, you should be able to completely ignore the later half of this document.  More to the point, if you stick to the standard datatypes like vector, map and string, they take care of all of this stuff for you!

 

If you find yourself using new, delete or working with a non const pointer, it should be an alarm bell of sorts.  Stop, take a closer look at your code and ask yourself "could I accomplish this task using a standard type?"  or "would a reference work instead?".  If the answer to either question is true, you are almost certainly better off refactoring your code.

Programming ,




RIM released version 1.6 of Gameplay, a cross platform 3D game development library

25. January 2013

 

Rim have released Gameplay 1.6, a 3D cross platform library for writing games for Blackberry 10, Playbook, PC, Mac, Android and iOS devices using C++.  gameplayThis is a project we have been following here at GameFromScratch for quite a while, and given the complexity, its amazing just how fast you can get up to speed.

 

If C++ is your language of choice ( or LUA for that matter ), you really should check out Gameplay, it’s completely free and open source.

 

The following are the release notes of the 1.6 release:

  • Adds file Stream interface for reading/writing files instead of using fread/fwrite.
  • Adds Terrain class to support for heightmap based terrains featuring LOD, multiple surface layers, loading from PNG, RAW8/16, full transform, physics, patch culling and verticle skirt for cracks.
  • Adds object-space normal map generation to gameplay-encoder for terrain normal map generation.
  • Adds scene support for loading .terrain files in .scene files.
  • Adds scene support for inline cameras to .scene files.
  • Adds suppoft for defining .scene files without 'path' to gpb. New node can not be create in .scene file.
  • Adds static Scene::getScene(const char*) to query currently active scenes in a game, helpful for script access.
  • Adds support for multiple translate, rotate and scale commands in a single node entity within .scene files, processed in-order they are defined.
  • Adds scene support for material auto binding scene ambient color, light color and light direction.
  • Adds support for setting the depth compare function on materials.
  • Adds support for texture/sampler arrays being passed to materials.
  • Adds support for loading uncompressed DDS textures for the following formats: R8G8B8, A8R8G8B8, A8B8G8R8, X8R8G8B8, X8B8G8R8
  • Adds improvments to prefer higher quality mipmap generation.
  • Adds improved Gamepad API support for button enumeration, triggers and some mobile Gamepad support on BlackBerry.
  • Adds additional gameplay-tests for billboards, forms, gamepads and lights.
  • Adds support for launching the browser via launchURL(const char*).
  • Adds physics support for setLinearFactor and setAngularFactor on rigid bodies.
  • Adds methods to PhysicsCollisionObject to allow conversion to subclass types (i.e. PhysicsRigidBody, PhysicsCharacter, etc) from script.
  • Adds option for fullscreen without width/height config to use native desktop resolution.
  • Adds Linux support for OpenAL PulseAudio back-end.
  • Adds support for latest Bullet Physics 2.81 with NEON optimizations for mobile targets.
  • Adds support for preprocessor directive NO_LUA_BINDINGS in the gameplay project to omit inclusion of generated lua bindings in compilation for developer mode value.
  • Adds optimizations to Lua generator to only write generated files if they differ from existing files, reducing both build times and committing of unchanged script binding files.
  • Adds changes to Slider for setValueTextVisible, setValueTextAlignment, setValueTextPrecision and getters.
  • Adds Microsoft Windows 7 64-bit support.
  • Adds Apple iOS 6 support.
  • Fixes to external-deps to reduce the size of the libraries on Windows.
  • Fixes for Android to no longer need to copy files to the SD card before reading them. None of the Android samples require an SD card.
  • Fixes for animation of opacity on UI and fonts.
  • Fixes in UI for removing controls and also setVisible(bool).
  • Fixes for UI controls missing on MacOSX.
  • Fixes for setting UI alignment programmatically.
  • Fixes for lighting shaders.
  • Fixes to the texture minification mode from GL_LINEAR_MIPMAP_LINEAR to GL_NEAREST_MIPMAP_LINEAR for newly created textures with mipmaps.
  • Fixes minor memory leaks and possible access violations when calling Game::exit() from script.
  • Fixes physics debug drawing for large scenes causing the internal MeshBatch to grow to an enormous size.

 

This release certainly makes Gameplay on the desktop seem much more viable.  Terrain support is certainly a nice new addition as well.

 

Good job Gameplay team.

News, Programming , , ,




RIM releases GamePlay 1.4

7. August 2012

logo_powered_black

I wrote sometime back about RIM’s open-source Gameplay SDK.  GamePlay is a complete 3D engine that targets Blackberry OS 10/PlayBook OS, Android, iOS, Windows and MacOS X.  They just announced the release of 1.4 and it’s full of some pretty nice additions:

 

New features

  • Lua script bindings on all public interfaces of the framework.
  • Script binding generator tool for creating user-defined Lua script bindings from Doxygen XML.
  • AI state machine for AI programming/scripting on game objects.
  • Virtual gamepad input support with custom theming using UI system.
  • Optimizations using NEON math for mobile platforms.
  • Compressed texture support for DXT, PVRTC, ATC and ETC1.
  • Improved modular shaders with support for #include in shaders and new light map support.
  • Optimizations and Improvements to the UI system such as inertial scrolling and scrollbars.
  • Pre-built versions of the gameplay-encoder and gameplay-luagen tools.
  • Optimizations in animation and physics.
  • Fixes to support Maya 2012/2013 COLLADA DAE_FBX export.
  • FBX 2013 format support.

 

The also announced their roadmap for future versions:

The ‘next’ branch features for v1.5, v1.6, v1.7

  • Linux support.
  • Vehicle physics.
  • AI path finding with navigation meshes.
  • Physical Gamepad input for Xbox 360, Wii, and Bluetooth® HID controllers.
  • Terrain.
  • Scene editor tool.

 

 

You can read the full announcement here or head over here to get started.  Lua scripting is a very nice addition, especially for those that prefer not to work at the C++ level ( include me in that camp! ).  Terrain and scene editing tools will go a long way towards helping adoption.

 

Nice work GamePlay team! 

 

If I could make a suggestion if anyone on the team is listening, I would recommend a rebrand at this point.  Gameplay is an apt name, but it is incredibly generic, meaning that your discoverability is going to be abysmal.  You’ve created a great product here, it would be a shame that people didn’t use it simply because they couldn’t find it!  Just adding a second word the next name (Gameplay NEXT GameplayGO Gameplay-A-GoGo) would help a ton and allow you to keep your existing documentation, website, etc… unchanged.

News ,




A series of OpenGL samples

3. July 2012

A poster, JakobProgsch, over on the TigSource forums has made a series of OpenGL samplesopengllogo available on GitHub. Each example is contained in a single file, doesn’t depend on any non-canonical libraries or hide code behind a framework.  As a results the examples are a bit longer, but easier to follow.

 

The following topics are covered ( description taken from each file header ).

 

Sample 1

Skeleton code that all the other examples are based on

 

Sample 2

This example shows the setup and usage of shaders and a vbo+vao

 

Sample 3

This example shows the setup and usage of shaders and a vbo+vao
In this example the attrbute locations are set via BindAttribLocation
instead of layout qualifiers in the shaders

 

Sample 4

same as the "Shader and VBO" example, only with an indexed vbo.

 

Sample 5

apply a texture to the fullscreen quad of "Indexed VBO"

 

Sample 6

set up a perspective projection and render a rotating cube

 

Sample 7

render the cube from the perspective example to a texture and

apply fxaa antialiasing to it.

 

Sample 8

create 8 instances of the cube from the perspective example

with an additional offset buffer and AttribDivisor

 

Sample 9

create 8 instances of the cube from the perspective example

the difference to the instancing1 example is that we are

using a texture buffer for the per instance data instead of a

vertex buffer with divisor.

 

Sample 10

create 8 instances of the cube from the perspective example

the per instance data is passed with a uniform buffer object

 

Sample 11

Uses a geometry shader to expand points to billboard quads.

The billboards are then blended while drawing to create a galaxy

made of particles.

 

Sample 12

This example uses the geometry shader again for particle drawing.

The particles are animated on the cpu and uploaded every frame by

mapping vbos. Multiple vbos are used to triple buffer the particle

data.

 

Sample 13

This example simulates the same particle system as the buffer mapping

example. Instead of updating particles on the cpu and uploading

the update is done on the gpu with transform feedback.

 

Sample 14

This example renders a "voxel landscape/cave" from the view of a

moveable camera. Occlusion queries and conditional rendering are used

to cull occluded parts of the world and timer queries are used

to measure the performance.

 

Hope he keeps them coming, good OpenGL resources are scarce.

 

Edit: 7/5/2012 Fixed links and added 14th sample, which by the way, is a bit of a monster.

Programming , ,