ComputerWorld Part 2

LovePosted by Eskil Sat, December 18, 2010 00:24:55

Betray is an easy to use portability library that lets you build single window OpenGL applications. It can be compared to GLUT or SDL, but has a more streamlined interface and supports a few more things. A very important feature of Betray is that it lets you write a single application that supports many different modes of input and outputs. The idea is not just to make it easy for application developers to write portable applications, but also for people who either make, or have access to special hardware to write their own versions of betray, so that all existing betray applications will support the hardware. It makes it much easier for hardware or interface developers, to test out their hardware with existing software. Closed source applications like Betray will soon be released with an Open source betray DLL so that anyone can rewrite it to work with any kind of input and output devices. The file b_test.c is a simple example program using much of the Betray API.

I invite anyone who wants to, to use, test, debug or help me to port betray to other platforms or hardwares to do so. If you are interested E-mail me at eskil at obsession dot se


While its good for Betray implementations to support as much as possible of the Betray API, this isnt always possible. A particular hardware may lack features such as pointer device of multi touch. Even if a feature is not implemented it still needs to be present in terms of API entry's, and should return reasonable default values, to make it easier to support. By using the functions betray_support_context and betray_support_functionality you can ask the implementation functionality is active in the implementation.

To initialize betray and create a screen you call the following:

void betray_init(BContextType context_type, int argc, char **argv, uint window_size_x, uint window_size_y, boolean window_fullscreen, char *name);

Currently Betray only supports OpenGL contexts, but in the future it may be extended to support other rendering contexts too. Once betray has been initialized you can use the functions, betray_action_func_set to give betray a function pointer to the action function that will act as the programs main loop, then call betray_launch_main_loop to start the applications main loop. The Main loop function will be called with a pointer to the structure BInputState that contains useful input state. In this structure you will also find the member "mode" that can be set to either, BAM_DRAW, BAM_EVENT, or BAM_MAIN. This member indicates why the main loop has been called, to either redraw the screen, handle input or compute (the compute call is where time should be advanced, and will be called even if the program has been minimized and is therefor useful to keep things like network connections alive that are not dependent on either being displayed or requires input form the user). The reason for having a single entry point for all three is that you can build nice libraries of interface functions that can handle all 3 modes. Consider this function:

boolean my_button(BInputState *input, float pos_x, float pos_y, char *name)

This function can now handle both drawing and handling input, independently, and the user only have to add it once to the code base, even if it gets called multiple times for different reasons.


While betray_init immediately gets you a screen to draw to, you can at any time modify the screen mode using betray_screen_mode_set. By setting x_size and/or y_size to zero in either betray_screen_mode_set or betray_init betray will revert to the size of the desktop. To find out the current size and state of the draw surface you can call betray_screen_mode_get that will also return the aspect ratio of the screen. In order to support head tracking and stereoscopic (3D) programs should use betray_view_vantage betray_view_direction to retrieve the position of the eye in relation to the screen and any camera rotations or movements.

Betray has a few OpenGL specific functions like betray_gl_proc_address_get to get access to extension function pointers, and betray_gl_context_update_func_set where the user can give betray a function pointer that will be called if the current OpenGL state is lost (this usually happens when screen modes are changed). To make it possible for a Betray implementation to render the entire application to a texture using FBOs, the function betray_gl_screen_fbo_get exists. When ever the betray application is using FBOs and would like to reset the draw target to 0 (the screen) it should instead reset it to the value returned by betray_gl_screen_fbo_get.


The input is divided in to 3 different category's, pointers, axis and buttons and Betray can support any number of each. Pointers are 2 dimensional screen pointers with one or more buttons. You can read out their position, delta position and the position of their last primary click. The later can be very useful when implementing buttons since a button can check both if a pointer is on a button and if it was at the tim of the click, and that means buttons does not need to store state. Using betray_set_mouse_warp the application can hide and continually warp the mouse pointer to the center of the screen in order to avoiding hitting the edges, something very useful for first person mouse controls. Buttons on pointing devices show both their current state and the state they were in the last frame, and it is therefore possible to know if the button is being pressed, released or held. For all buttons you can use the betray_button_get_up_down to store your own state for any button you want. If the user is expected to type in text, it is good to call betray_button_keyboard to enable betray to show a on-screen keyboard on platforms without physical keyboards. Axis are essential any 1, 2 or 3 dimensional input such as joysticks, pedals, accelerometers and so on.


Betray also has a API for 3D sounds that lets you load sounds (using betray_audio_sound_create), set a listener (using betray_audio_listener) and then play the sounds (using betray_audio_sound_play). Once a sound has been started it can be modified using betray_audio_sound_set and betray_audio_sound_stop.


To help betray applications better integrate with the operating system it also supports accessing text strings from the clipboard, and the ability to launch open and save file requesters.


Finally betray supports basic thread functionality that lets you create threads and create, lock and unlock thread safe locks.


Betray has just been rewritten and I have yet to port over Love or any other applications to the new API. Seduce will be the first library that will be ported over to the new version of betray. At the moment Betray is only implemented for Win32, but other operating systems will soon follow. I hope to get as many developers as possible to use and contribute to Betray so that we can make multi platform development easier for everyone.

The library can be downloaded from
Or you can view the betray.h file at

  • Comments(5)

Fill in only if you are not real

The following XHTML tags are allowed: <b>, <br/>, <em>, <i>, <strong>, <u>. CSS styles and Javascript are not permitted.
Posted by Peter Lu Tue, December 21, 2010 23:22:44

Hey Eskil,

I love what you are doing here. I'm glad to see betray as well as the remainder of your applications are being brought out to light again. These applications and api's seem very well written with carefully aimed motives and deserve more attention.

As I am rather naive with the world of open source programming I must ask. Why not put your applications under a public repository (like github, sourceforge, etc...) and set up a community site not encourage both community use and development. Sometime around summer I had considered adopting all the quelsolaar api (seduce and betray) as the foundation for my applications but found the site and documentation hard to navigate and ended up giving up. A community site would make it far easier to offload not just porting work but general documentation and press work much easier. I ended up opting for GLUT and openframeworks as both having much better documentation and examples and a system for distribution.

Posted by ChicOrtiz Sat, December 18, 2010 23:21:25

Hi Eskil!

Looks awesome, thank you so much for sharing. Maybe it's a nice thing to have a very simple example demonstrating what it can do... Why not carry on with that asteroid game but 3D and "Multiplayer" (<only 2 players)? Or something even simpler? So you are able to demonstrate verse + LoqAirou + game logic working together. The new version of LoqAirou running on windows works fine with that old version of verse for linux inside the Uni-verse website. The .dmg file inside Uni-verse doesn't work anymore if you install it, it doesn't has the verse server. I found the verse server alone compiled somewhere in the internet for mac and it works well, but it is not official i guess, it's just something I found on a very old sharing website. I can email it for you if you want. Here is how I'm using LoqAirou inside MacOSX at the moment: I run that weird verse server I found somewhere in the web, then I run the .vml saver, loader and LoqAirou via wine.

So, looks like we already has verse compiled for Mac, Win and Linux and it is still functional so I believe it would be a very good thing to have a new version of LoqAirou, vml saver and loader compiled for Linux Ubuntu, and Macosx, plus your... Engine? I mean to demonstrate your main apps working together inside those platforms. It would be nice to have a kind of LoqAirou to prototype Logic via verse, I guess that was the intention of Emil with Puyo?. Imagine the asteroids game again but you can change the shape of the asteroids in real time and the shape of the spaceships (considering you have 2).

I though the verse saver would be something simple to compile under MacOsx but I need to start with something even simpler because Xtools looks dawn complicated.

All the best for your new... Core?



Posted by n Sat, December 18, 2010 10:34:01

compilation error due to forge.h's declaration of the f_raycast_tri_culld function. It has float rather than double in one of the vertices

Posted by sinoth Sat, December 18, 2010 02:57:13

D'oh, sorry, missed the instructions at the top to just shoot you an e-mail :)

Posted by sinoth Sat, December 18, 2010 02:55:15

How do you want us to submit patches? I'm having to change quite a bit of stuff to get it to compile with GCC.