Archive for May, 2012

Box2D-Shiva-Wrapper: Demo Project

May 26th, 2012

Not too much news regarding the actual Box2D wrapper today. I rather spent the last days on coming up with a little demo project (proof of concept for the plugin). I already got a rough prototype up and running, but the time isn’t right yet to release any info to public. Fact is, that this demo already has brought up some issues that I fixed and besides that, I started expanding the API:

applyAngularImpulse
applyForce
applyForceToCenter
applyLinearImpulse
applyLinearImpulseToCenter
applyTorque
setBodyActive
setBodyAwake
destroyBody
getBodyLinearVelocity
getAngleBetweenPoints

Not too much, but more is coming!

Now back to some concept art (nice alternative to too much programming :) )!

Box2D-Shiva-Wrapper: Compiling Box2D As Plugin

May 16th, 2012

I will write which stones I fell over during the process of getting Box2D to compile as a ShiVa-Android-plugin. This could also be useful for anybody who wants to use STL on Android.

Disclaimer: I am far no C++, build or make file guru. If you spot anything, which could be done better, please tell me (I am willing to learn).

Enabling STL

First, modify the MyPlugin.makefile (located in “/ShiVaEditor/Data/PluginTemplate/Make/Android/”) such that CPPFLAGS looks like this:

CPPFLAGS            = -fno-rtti -I"$(ANDROID_NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/include" -I"$(ANDROID_NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include"

Then in ShiVa, regenerate your Android plugin makefile and click on recompile (RE-compile, not compile). If everything works out right, you should see the red circle next to the android plugin turned green:

Now you’re ready to export!

Export your game with the Android profile selected. This is important, because when using plugins, only the selected profile version of the plugin is packed into the STK. So if you export with the DefaultProfile, the Android plugin will probably be missing! Note: After exporting, you can always look at the yourgame.xml to see what files are packed into the STK. Just open it with your browser.

With the freshly exported STK, now create an Android project with UAT. Unzip it’s contents and make the following changes to these two files:

root/build.xml:
Add the line

APP_STL			 := gnustl_static

to where the Application.mk is defined (2 spots in the build.xml: for release and debug).

root/jni/Android.mk:
Add the line

LOCAL_LDLIBS           += -lgnustl_static

after the last LOCAL_LDLIBS assignments.

Now compile the build.xml and hope that everything works :) I have come accross some weird build errors, they are handled in the next section.

Credits to this whole procedure go to supernat on this thread in the ShiVa forum! In case you want to use STLPORT instead of GNUSTL, you can see what changes need to be made over at the forum. I stuck with GNUSTL. Also big thanks to Dominik from StarkApps.

Box2D Specific Modifications

Precompiled Headers

I don’t really have a clue, what precompiled headers do (nice rhyme eh?), but I managed to get them to compile. In the end, I had to add a #include "PrecompiledHeader.h" to nearly every Box2D source file (the compiler gave some tips/warnings that I must do so). As I had done this, the plugin started to compile for Windows. For Android, I got some weird error like “error in algorithm” or “error in stdlib.h”, which were quite misleading.

In the end, I simply MOVED the failing include statements to the precompiled header file (meaning removing them from the Box2D sources and adding them to the precompiled header file), leading to these additional include statements in the precompiled header file (~ stands for < or > …had some trouble with html editor):

#include ~stdlib.h~
#include ~cstdlib~
#include ~cstdio~
#include ~cstdarg~
#include ~climits~
#include ~cstring~
#include ~memory~
#include ~algorithm~

The funny thing now is, there’s a precompiled header file for each platform and I only added these includes to the windows one. I actually don’t know why this is working on Android, but sometimes you just have to stop asking questions :) If anybody out there has an idea, please tell me.

b2BroadPhase And std::sort

The file b2BroadPhase.h has a call to std::sort, which the Android compiler complained that he can’t find. Looking at the GNUSTL headers/templates, it read like that for GNUSTL, this isn’t in the std namespace … but I’m not sure about that one. Reading headers and templates in notepad++ isn’t a good idea with all those macros and defines. For the first version, I just commented the line out, as it’s just a performance optimization anyway.

Includes

Don’t use backslashes in include statements, use slashes! Meaning don’t write #include "Box2D\Box2D.h", instead write #include "Box2D/Box2D.h". Not sure if this would have also failed on Android, but on iOS it raised an error.

 

That was it for now. I’ll keep updating the issues list as I keep working on it and maybe I’ll have some insights on the unclear points.

Box2D-Shiva-Wrapper: The API

May 11th, 2012

As of ShiVa 1.9.x, you can’t really create data structures. So if you e.g. want to translate something by X/Y/Z, you don’t have a vector data type with the members vector.x/vector.y/vector.z meaning you then can’t call myAPI.translate(myVector). Instead you have to call myAPI.translate(X, Y, Z).

This gets a bit complicated as soon as you have tons of possible parameters, like when wrapping the Box2D b2Body class. After a bit of discussion, we came to the conclusion, that using hashtables will do the trick. The drawback is, that you have to know the name of the properties, as they are entered as a string, but warnings are logged as soon as you do something wrong … and one could create constants for the keys to make it “end user safe”. Also, the end user actually shouldn’t really need to touch this piece of code anyway as stated in my first post.

So here is how the creation of a body looks like in StoneScript:
(Please not that this code uses all the body properties – most of them are optional)

local hObject = this.getObject ( )
 
local hBodyDef = hashtable.newInstance ( )
 
if ( hBodyDef )
then
	local nPosX, nPosY, nPosZ = object.getTranslation ( hObject, object.kGlobalSpace )
	local nRotX, nRotY, nRotZ = object.getRotation( hObject, object.kGlobalSpace )
	local nAngleRad = nRotZ * 0.0174532925 --google says: 1 degree = 0.0174532925 radian :)
 
	hashtable.add ( hBodyDef, "active",             this.bActive ( ) )
	hashtable.add ( hBodyDef, "allowSleep",         this.bAllowSleep ( ) )
	hashtable.add ( hBodyDef, "angle",              nAngleRad )
	hashtable.add ( hBodyDef, "angularDamping",     this.nAngularDamping ( ) )
	hashtable.add ( hBodyDef, "angularVelocity",    this.nAngularVelocity ( ) )
	hashtable.add ( hBodyDef, "awake",              this.bAwake ( ) )
	hashtable.add ( hBodyDef, "bullet",             this.bBullet ( ) )
	hashtable.add ( hBodyDef, "fixedRotation",      this.bFixedRotation ( ) )
	hashtable.add ( hBodyDef, "gravityScale",       this.nGravityScale ( ) )
	hashtable.add ( hBodyDef, "linearDamping",      this.nLinearDamping ( ) )
	hashtable.add ( hBodyDef, "linearVelocity.x",   this.nLinearVelocityX ( ) )
	hashtable.add ( hBodyDef, "linearVelocity.y",   this.nLinearVelocityY ( ) )
	hashtable.add ( hBodyDef, "position.x",         nPosX )
	hashtable.add ( hBodyDef, "position.y",         nPosY )
	hashtable.add ( hBodyDef, "type",               this.sType ( ) )
	hashtable.add ( hBodyDef, "callbackAI",                 this.sCallbackAI ( ) )
	hashtable.add ( hBodyDef, "callbackOnBeginContact",     this.sCallbackOnBeginContact ( ) )
	hashtable.add ( hBodyDef, "callbackOnContact",          this.sCallbackOnContact ( ) )
	hashtable.add ( hBodyDef, "callbackOnEndContact",       this.sCallbackOnEndContact ( ) )
 
	maBox2d.createBody ( hObject, hBodyDef )
end

And this is how the creation of a shape looks like in StoneScript:
(Please note that the scale and center calculation isn’t required for the actual creation of the shape)

--Get the root object, which has the box2d body applied ...
local hObject       = this.getObject ( )
local hBox2dObject  = object.getParent ( hObject )
 
if( hBox2dObject and maBox2d.hasBody ( hBox2dObject ) )
then
	local nAngleRad = this.nAngle ( ) * 0.0174532925 --google says: 1 degree = 0.0174532925 radian
 
	if( this._bUseObjectScaleAsSize ( ) )
	then
		local nScaleX, nScaleY, nScaleZ = object.getScale ( hObject )
		this.nWidth ( nScaleX )
		this.nHeight ( nScaleY )
	end
 
	if( this._bUseObjectPositionAsOffset ( ) )
	then
		local nPosX, nPosY, nPosZ = object.getTranslation ( hObject, object.kParentSpace )
		this.nCenterX ( nPosX )
		this.nCenterY ( nPosY )
	end
 
	local nCategoryBits  = maBox2d.convertBitsToInt ( this.tCategoryBits ( ) )
	local nMaskBits      = maBox2d.convertBitsToInt ( this.tMaskBits ( ) )
 
	local htShapeDef = hashtable.newInstance ( )
	--Shape def properties:
	hashtable.add ( htShapeDef, "density",              this.nDensity ( ) )
	hashtable.add ( htShapeDef, "friction",             this.nFriction ( ) )
	hashtable.add ( htShapeDef, "isSensor",             this.bIsSensor ( ) )
	hashtable.add ( htShapeDef, "restitution",          this.nRestitution ( ) )
	hashtable.add ( htShapeDef, "filter.categoryBits",  nCategoryBits )
	hashtable.add ( htShapeDef, "filter.maskBits",      nMaskBits )
	hashtable.add ( htShapeDef, "filter.groupIndex",    this.nGroupIndex ( ) )
 
	--Box shape properties:
	hashtable.add ( htShapeDef, "width",    this.nWidth ( ) )
	hashtable.add ( htShapeDef, "height",   this.nHeight ( ) )
	hashtable.add ( htShapeDef, "center.x", this.nCenterX ( ) )
	hashtable.add ( htShapeDef, "center.y", this.nCenterY ( ) )
	hashtable.add ( htShapeDef, "angle",    this.nAngle ( ) )
 
	this.sShapeId ( maBox2d.addShapeBox( hBox2dObject, htShapeDef ) )
end

The above code is actually only used at object creation time. If you have to change single properties during runtime, like maybe modifying the friction value of a shape, there will be API functions for that. You will then write something like maBox2d.setFriction( sShapeId, nFriction ). At this point, I cannot provide a complete list yet … but you see, that it will be more comfortable and safer than the hashtables :)

Next up is plugin compilation for Android!

By the way: I am now using the awesome StoneScript syntax highlighting provided by makkar from Archimmersion! Be sure to check it out if you’re running your own ShiVa related blog.

Box2D-Shiva-Wrapper: First Test

May 6th, 2012

I recently started a little hobby project: try to get Box2D running inside ShiVa 3D with support for PC, iOS and Android.

Here is the result so far: http://www.youtube.com/watch?v=Nj4F4IvrWTw

Features:

  • Body properties wrapped
  • Shapes wrapped: box, circle, poly, (also compound shapes are possible)
  • Optional collision callbacks per object
  • Mouse joint
  • Collision groups

Running on:

  • PC
  • iOS: iPod Touch 4g (60FPS)
  • Android: HTC Desire (60FPS)

Special Note: All objects are composed in the scene! No additional object creation via script required … well, sort of ;)

A bit more detail …

My main goal is to be able to create physic game prototypes as fast as possible. This means for me, as much WYSIWYG as possible. Take that stack of crates for example: I don’t want to write a for-loop and create them via script, I want to create them inside the ShiVa-viewport. Otherwise I could simply use the Box2D-Testbed and wouldn’t need the wrapper in the first place.

This led me to the following ShiVa-model setup:

  • Each model must have one Box2D-body-AI (typically a helper object).
  • The model with the Box2D-body-AI can have numerous children which have Box2D-shape-AIs. This way you can also create compound shapes, like the three linked crates you also see in the video.

Here is a screenshot showing these two AI-models as well as the model hierarchy:

So for the “stack of crates”-model (image on the left), I first created a box model and set that up (the two AI models as mentioned above). Then in the “stack of crates”-model, I simply stacked multiple box models. And this can now be used in the actualy scenes anytime I want. The body/shape-AI-models expose all needed properties to setup those objects. If value changes at runtime are needed, I’ll create some scripting functions for that. I don’t have a real list yet, my plan is to create a game, and create the functions on the fly as I need them (just in time, not just in case ;) ).

For runtime object creation, there will also probably be some factory functions, like “box2d.createSimpleBox”, but my suggested way of creating runtime objects is to create your model-templates and then just write scene.createRuntimeObject … you get what I mean :)

This wraps up my first post about the Box2D-ShiVa plugin. I have no eta and currently no plan how and when it will be available for public. After all, this is currently a hobby project. In my next posts, I’ll cover how the scripting API looks like to set things up and how I got Box2D to compile inside a ShiVa plugin for Android, which was a bit tricky – at least for me, as I am no build/make file guru …

Last, but definitely not least: big thanks go to NiCoX from Stonetrip, for giving me some awesome tips on how to structure the plugin. Thanks!