Main Menu

Box2D Wrapper

Started by slayer93, October 26, 2008, 03:04:29 PM

Previous topic - Next topic

slayer93

Thanks, I'll be improving the actual plugin this weekend :)

Glad it works

thaaks

Did you create your own wrapper dll to call the Box2D dll or is PBBox2d.dll just a renamed version of the Box2D dll?

I hope to give this a test run tonight!

Great stuff for PB, thanks a lot slayer93!

slayer93

QuoteDid you create your own wrapper dll to call the Box2D dll or is PBBox2d.dll just a renamed version of the Box2D dll?

I created my own wrapper.


Have fun! :)

kevin

#18
     Had bit of play with this last night, and was a somewhat shocked by just how slow Box2D seems to be.   The processing time seems directly proportional to the object count (ie. recursive)).  So the more objects, the slower the simulation gets.  Takes 30->35 milliseconds to process 50 moving objects,  60->100 milliseconds for 100 objects etc.  Much quicker when they're at rest.  Which is a bit of a worry really.


PlayBASIC Code: [Select]
; Setup
SetFPS 30
CreateCamera 1
RenderToScreen

; Use Box2D
#include "box2D"

; Create a new world
wID=B2DCreateNewWorld( -100.0, -100.0, 200.0, 200.0, 0.0, 0.5 )
B2DSetWorldStep( wID, 1.0 / 60.0 )
B2DSetWorldVelocity( wID, 1.0 )
B2DSetWorldIterations( wID, 10.0 )
B2DSetWorldMtPRatio( wID, 10.0 )

; Create a ground Body
boxc 0,0,200,10,1,rgb(0,0,120)
getImage 1,0,0,200,10

gID = B2DCreateNewBody( )
B2DSetBodyPosition( gID, 15.0, 50.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 10.0, 0.5 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

gID = B2DCreateNewBody( )
B2DSetBodyPosition( gID, 35.0, 45.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 10.0, 0.5 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

; Create Boxes
Boxc 0,0,20,20,1,rgb(100,0,0)
getImage 2,0,0,20,20
preparefximage 1
preparefximage 2
; -----------------------------------------------------------
; -----------------------------------------------------------
; Change 20 to different numbers to create more or less boxes
; -----------------------------------------------------------
; -----------------------------------------------------------
For i=2 to 100
bID = B2DCreateNewBody( )
B2DSetBodyPosition( bID, rnd(500)/10, rnd(200)/10 )
B2DBuildBody( bID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 1.0, 1.0 )
B2DSetShapeFriction( sID, 0.1 )
B2DSetShapeDensity( sID, 1.0 )
B2DAddShapetoBody( bID, sID )
B2DCalculateBodyMass( sID )
spr = newSprite(0, 0, 2)
AutoCenterSpriteHandle spr, 1
SpriteDrawMode spr,2
B2DLinkSpriteToBody( spr, bID )
Next i



; Main Loop
Do
CLS 0

; Update Box2D World
t=timer()
B2DUpdateWorld( wID )
t=timer()-t

if T>Max then Max=t

print FPS()
print t
print max


Sync
Loop





slayer93

#19
Yeah, I'm going to look a bit harder at my code over the weekend and see if I can speed this up before I add more features...apparently it seems that right now I'm making myself known to make really slow programs :P.

But after a real quick google just now I happen to come across this - http://www.box2d.org/forum/viewtopic.php?f=8&t=1474. So I think Box2D shouldn't update every sync but update on a timer.

I think I have to implement this into the wrapper, so I'll do this on the weekend (unfortunately I can't do it now). I'll also look for other things that might be slowing it down.

Hopefully I can get it to simulate 100 bodies easily over the weekend.

Thanks for the test Kevin, it really showed me the problem :)

Edit: Quick Test, this seemed to work well

PlayBASIC Code: [Select]
; Setup
SetFPS 0
CreateCamera 1
RenderToScreen

; Use Box2D
#include "box2D"

; Create a new world
wID=B2DCreateNewWorld( -100.0, -100.0, 200.0, 200.0, 0.0, 0.5 )
B2DSetWorldStep( wID, 1.0 / 60.0 )
B2DSetWorldVelocity( wID, 1.0 )
B2DSetWorldIterations( wID, 10.0 )
B2DSetWorldMtPRatio( wID, 10.0 )

; Create a ground Body
boxc 0,0,200,10,1,rgb(0,0,120)
getImage 1,0,0,200,10
preparefximage 1

gID = B2DCreateNewBody( )
B2DSetBodyPosition( gID, 15.0, 50.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 10.0, 0.5 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

gID = B2DCreateNewBody( )
B2DSetBodyPosition( gID, 35.0, 45.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 10.0, 0.5 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

; Create Boxes
Boxc 0,0,20,20,1,rgb(100,0,0)
getImage 2,0,0,20,20
preparefximage 2

; -----------------------------------------------------------
; -----------------------------------------------------------
; Change 20 to different numbers to create more or less boxes
; -----------------------------------------------------------
; -----------------------------------------------------------
For i=2 to 100
bID = B2DCreateNewBody( )
B2DSetBodyPosition( bID, rnd(500)/10, rnd(200)/10 )
B2DBuildBody( bID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 1.0, 1.0 )
B2DSetShapeFriction( sID, 0.1 )
B2DSetShapeDensity( sID, 1.0 )
B2DAddShapetoBody( bID, sID )
B2DCalculateBodyMass( sID )
spr = newSprite(0, 0, 2)
AutoCenterSpriteHandle spr, 1
SpriteDrawMode spr,2
B2DLinkSpriteToBody( spr, bID )
Next i

t=timer()

; Main Loop
Do

CaptureToScene
ClsScene

text 0,0,FPS()

; Draw the Box2D World
B2DDrawWorld( wID )

; Update Box2D World
if (Timer()-t) > 16
B2DUpdateWorld( wID )
t=timer()
endif

DrawCamera 1

; Sync
Sync
Loop


kevin


Any progress with this ?

 

slayer93

Yeah, I just want to make it timer based(which should fix the frame rate problems) and rearrange some things so it is a little easier for me. I should be able to show a few things sometime this week.

kevin

#22
 Having not really looked at Box2D library,  I'm not sure I follow that, I assumed the simulation was built in.  But anyway,  What I would like to see :) is something up and running prior to the next TGC news letter.    Chop Chop :)


slayer93

QuoteHaving not really looked at Box2D library,  I'm not sure I follow that, I assumed the simulation was build in.

Box2D is handling the simulation, it was my fault that it was running slow.
The reason I think the frame rate was so low was because I used a for/next loop to update Box2D 60 times(internally). So each time you called B2DUpdate it would update the simulation 60 times. Why did I do that? Well for some reason I thought since it had to be updated 60 times for a complete step I should loop through it 60 times to make that complete step. The time step for each world is in Hz per second(frequency it is called), so when I used B2DSetWorldStep and put 1/60 it just said it is at 60 Hz per second. But instead of that I called it 60 times each sync and setting that to 60 FPS basically called it 3600 times each second, no doubt making the FPS dive. But it's a bit strange right now because if I update it once per sync (at 60 FPS) it moves incredibly slow, so I still have to figure that out as I sure it is another silly mistake I am making. Calling it to few times maybe, not sure? Anyway I plan to internally setup a timer based system (according to this article - http://gafferongames.wordpress.com/game-physics/fix-your-timestep/ -because people seem to agree it is a good way to do it) and it should solve my update problems because it doesn't rely on the frame rate.

Hope I didn't sound like I was spouting nonsense. I'm still far from understanding everything about Box2D still.

QuoteBut anyway,  What I would like to see Smiley is something up and running prior to the next TGC news letter.

I can manage that :)

slayer93

#24
Ok, finally an update!

Sorry it took so long and I only added a few things too :-\. What's new?

- Turn shapes into sensors
- Changed some of the setBody commands to setBodyDef because of new commands
- Added get State commands
- Added filters (allows bodies to collide with one thing but not the other)
- Set and Get Linear and Angular Velocity

This is untested thus far and I plan on testing it while I make my new demo but might as well put it out there for any one who wants to try. New Commands are in the Read-Me.

I was also able to find out why things were so slow and I'm pretty ashamed that I didn't find out sooner. I put the gravity so low(before because it was so fast with 3600 calls), it was at 0.5 and once I put it at 9.8 it was looking a lot better. I also added in a temporary timer system which calls the update command every few milliseconds. I plan to put in a more advanced one later based on the advice from the article I posted earlier but for now it will have to do.

But my plan for now is as follows...

- Create a section on my website for the PlayBasic Box2D Port to host documentation and demos(later on) so you can have it as a reference(will post once ready).
- Make a new demo that shows off Box2D a lot better.
- Fix anything that doesn't work correctly.
- Add Joint Commands(this probably won't be till next week).

Download - (login required)

Here is an updated demo to try with the updated library.

PlayBASIC Code: [Select]
; PROJECT : Box2D Demo
; AUTHOR : Christian Ang
; CREATED : 10/19/2008
; EDITED : 11/14/2008
; ---------------------------------------------------------------------

; Setup
SetFPS 0
CreateCamera 1
RenderToScreen

; Use Box2D
#include "box2D"

; Create a new world
wID=B2DCreateNewWorld( -100.0, -100.0, 200.0, 200.0, 0.0, 9.8 )
B2DSetWorldStep( wID, 1.0/60.0 )
B2DSetWorldVelocity( wID, 10.0 )
B2DSetWorldIterations( wID, 10.0 )
B2DSetWorldMtPRatio( wID, 10.0 )

; Create a ground Body
boxc 0,0,200,10,1,rgb(0,0,120)
getImage 1,0,0,200,10
preparefximage 1

gID = B2DCreateNewBody( )
B2DSetBodyDefPosition( gID, 15.0, 50.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 10.0, 0.5 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

gID = B2DCreateNewBody( )
B2DSetBodyDefPosition( gID, 35.0, 45.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 10.0, 0.5 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

; Create Boxes
Boxc 0,0,20,20,1,rgb(100,0,0)
getImage 2,0,0,20,20
preparefximage 2

; -----------------------------------------------------------
; -----------------------------------------------------------
; Change 20 to different numbers to create more or less boxes
; -----------------------------------------------------------
; -----------------------------------------------------------
For i=2 to 100
bID = B2DCreateNewBody( )
B2DSetBodyDefPosition( bID, rnd(500)/10, rnd(200)/10 )
B2DBuildBody( bID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 1.0, 1.0 )
B2DSetShapeFriction( sID, 0.1 )
B2DSetShapeDensity( sID, 1.0 )
B2DAddShapetoBody( bID, sID )
B2DCalculateBodyMass( sID )
spr = newSprite(0, 0, 2)
AutoCenterSpriteHandle spr, 1
SpriteDrawMode spr,2
B2DLinkSpriteToBody( spr, bID )
Next i

; Main Loop
Do

CaptureToScene
ClsScene

text 0,0,FPS()

; Draw the Box2D World
B2DDrawWorld( wID )

; Update Box2D World
B2DUpdateWorld( wID, 16 )
DrawCamera 1

; Sync
Sync
Loop


kevin


Yep, that one works much smoother than before..  Well done ! 

  One concern I is the world creation can really chew through some time.  Ie. if I bump the count 500 it eats over second it create the objects. Any ideas ?

slayer93

It is probably because of my find ID functions because it has to go through an entire array to find the next free id. Which was probably a bad idea to begin with. I'll change those set of functions to not do that and find an ID a quicker way.

kevin


  Any luck coming up with a demo ? :)

slayer93

#28
Sorry, not to much has been updated, I can only work on the weekends but I did a bit today, will do more this weekend or at least over Thanksgiving (if I don't pig out and get to lazy :P).

Put some things into the dll internally (finding unused IDs) which actually made creating new things much faster, but I will probably use a more efficient method later on. So no new commands have been put in yet.

Same Download link...

Download - (login required)

and you can also get it as a zip...

Download - (login required)

Here is a demo I quickly made based on an example I saw in the testbed, not super interesting but more interesting than boxes falling.

PlayBASIC Code: [Select]
; PROJECT : Verticle Stack
; AUTHOR : Christian Ang
; CREATED : 11/21/2008
; EDITED : 11/22/2008
; ---------------------------------------------------------------------


;
; Setup
SetFPS 0
CreateCamera 1
RenderToScreen

;
; Include the Box2D library for use
#include "box2D"

;
; Create a box2d world to handle all the physics simulation
wID=B2DCreateNewWorld( -100.0, -100.0, 150.0, 150.0, 0.0, 9.8 )
B2DSetWorldStep( wID, 1.0/60.0 )
B2DSetWorldVelocity( wID, 10.0 )
B2DSetWorldIterations( wID, 10.0 )
B2DSetWorldMtPRatio( wID, 10.0 )

;
; Create the ground on which all the bodies will rest on
boxc 0,0,2500,20,1,rgb(0,0,120)
getImage 1,0,0,1500,10
preparefximage 1

gID = B2DCreateNewBody( )
B2DSetBodyDefPosition( gID, 75.0, 60.0 )
B2DBuildBody( gID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 125.0, 0.1 )
B2DAddShapetoBody( gID, sID )
gSpr = newSprite( 0, 0, 1 )
AutoCenterSpriteHandle gSpr, 1
B2DLinkSpriteToBody( gSpr, gID )

;
; Create 8 columns of 10 bodies on top of each other

; Create Boxes
Boxc 0,0,19,19,0,rgb(100,0,0)
getImage 2,0,0,20,20
preparefximage 2

for y=1 to 8
for x=1 to 10
bID = B2DCreateNewBody( )
B2DSetBodyDefPosition( bID, y*8.0, 60.0-x*2.0 )
B2DBuildBody( bID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 1.0, 1.0 )
B2DSetShapeFriction( sID, 0.1 )
B2DSetShapeDensity( sID, 1.0 )
B2DAddShapetoBody( bID, sID )
B2DCalculateBodyMass( sID )
spr = newSprite(0, 0, 2)
AutoCenterSpriteHandle spr, 1
SpriteDrawMode spr,2
B2DLinkSpriteToBody( spr, bID )
next x
next y

;
; Create a bullet to shoot
Boxc 0,0,19,19,0,rgb(0,200,0)
getImage 3,0,0,20,20
preparefximage 3

bID = B2DCreateNewBody( )
B2DSetBodyDefPosition( bID, -50.0,50.0 )
B2DSetBodyDefSleeping( bID, 1)
B2DBuildBody( bID )
sID = B2DCreateNewShape( )
B2DSetShapeAsBox( sID, 1.0, 1.0 )
B2DSetShapeFriction( sID, 0.1 )
B2DSetShapeDensity( sID, 1.0 )
B2DAddShapetoBody( bID, sID )
B2DCalculateBodyMass( sID )
spr = newSprite(0, 0, 3)
AutoCenterSpriteHandle spr, 1
SpriteDrawMode spr,2
B2DLinkSpriteToBody( spr, bID )


;
; Main Loop
Do

CaptureToScene
ClsScene

text 0,0,FPS()
text 0,20,"Verticle Stack Demo - Press Spacekey to launch bullet"

if SpaceKey()=1
fire=1
B2DApplyForce( bID, 0.0, 0.0, 0.0, 0.0 )
firetime=timer()
endif

if fire=1
B2DSetBodyLinearVelocity( bID, speed#, 0.0)
inc speed#
if timer()-firetime > 500 then fire=0
endif

; Draw the Box2D World
B2DDrawWorld( wID )

; Update Box2D World
B2DUpdateWorld( wID, 16 )
DrawCamera 1

; Sync
Sync
Loop



Edit: Forgot to show a nice little screenshot

kevin

#29

   Nice,  I can see this library becoming part of a PB release one day..