Box2D Forums

It is currently Wed May 22, 2013 12:18 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Sat Aug 21, 2010 2:23 pm 
Offline

Joined: Mon Aug 16, 2010 11:09 am
Posts: 128
Weird stuff going on with Delphi port of Box2D

The application creates many balls like below...

Then I want to simply draw them like so:

Code:
      for vBallIndex := 0 to mBallCount-1 do
      begin
         mBall[vBallIndex].Draw( OpenGLAPI );
      end;


But all balls draw samiliaryly... it seems as if there is only one ball ?!?

I checked the constructor and it seems there is only one mCircle ?!?!

All ball instances point towards the same mCircle ?!?

I am not even sure if there are multiple ball instances ?!?

But when I use the "body lists", "fixture lists" and such it does more or less work
with the drawing ?!?!

Very weird situation because I know Delphi pretty well... and it's supposed to create
multiple objects like I tell it to below ?!? But it doesn't seem to do that ?!?

I can think of a number of possibilities:

1. Compiler bug.
2. Box2D does something special.
3. Special memory manager being used ?
4. My IDE is momentarily corrupted ?!?!?

Weird:

Code:

type
   TBall = class
   private

   protected

   public
      mBodyDefinition : Tb2BodyDef;
      mFixtureDefinition : Tb2FixtureDef;

      mCircle : Tb2CircleShape;
      mRadius : double;
      mBody : Tb2Body;
      mFixture : Tb2Fixture;

      constructor Create( ParaWorld : Tb2World; ParaPositionX, ParaPositionY, ParaRadius : double );
      destructor Destroy; override;

      procedure Draw( ParaOpenGLAPI : TOpenGLAPIVersion110 );
   end;

constructor TBall.Create( ParaWorld : Tb2World; ParaPositionX, ParaPositionY, ParaRadius : double );
begin
   inherited Create;

   mBodyDefinition := Tb2BodyDef.Create;
   mBodyDefinition.bodyType := b2_dynamicBody;
   mBodyDefinition.position.SetValue( ParaPositionX, ParaPositionY );
   mBodyDefinition.bullet := true;

   mCircle := Tb2CircleShape.Create;
   mCircle.m_radius := ParaRadius;

   writeln( longword(mCircle) );    // all circles have same pointer ?!?! huh ?!?!?

   mFixtureDefinition := Tb2FixtureDef.Create;
   mFixtureDefinition.shape := mCircle;
   mFixtureDefinition.density := 1;
//   mFixtureDefinition.friction := 0.03;
   mFixtureDefinition.friction := 0;
   mFixtureDefinition.restitution := 1.0;

   mBody := ParaWorld.CreateBody( mBodyDefinition, True );
   mFixture := mBody.CreateFixture( mFixtureDefinition, true, true, true );
end;



(Also this first post on this new board section ! =D)

Bye,
Skybuck.


Last edited by Skybuck on Sat Aug 21, 2010 2:44 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sat Aug 21, 2010 2:32 pm 
Offline

Joined: Mon Aug 16, 2010 11:09 am
Posts: 128
Hmm

This line seems to have something to do with it:

mFixture := mBody.CreateFixture( mFixtureDefinition, true, false, true );

Setting it to false keeps the shape... otherwise the shape is freeed...

But why writeln would show all pointers the same is kinda weird... because
it's called before that... maybe it has something to do with critical sections...

or maybe delphi postpones the writeln until after the constructor is finished...

or maybe it's simply a constructor bug in Delphi 2007 it had other constructor bugs...

Bye,
Skybuck.


Top
 Profile  
 
PostPosted: Sat Aug 21, 2010 2:38 pm 
Offline

Joined: Mon Aug 16, 2010 11:09 am
Posts: 128
Ok, I am used to freeing everything myself... I am used to have all objects existing... having them not existing seems kinda dangerous to me ;) :)

I noticed how other objects seem to not exist as well.. it's apperently because of the auto-free features for box2d... apperently it immediatly frees stuff...

I thought it would only free stuff on shutdown... but apperently it does it immediatly...

So instead I have set everything to false, the only thing I am not sure about is the "CreateFixture" does it automatically clean up the fixtures for the bodies ?
(I think so...) (Also what does auto reset mass do ?)

better constructor:

Code:
   mBodyDefinition := Tb2BodyDef.Create;
   mBodyDefinition.bodyType := b2_dynamicBody;
   mBodyDefinition.position.SetValue( ParaPositionX, ParaPositionY );
   mBodyDefinition.bullet := true;

   mCircle := Tb2CircleShape.Create;
   mCircle.m_radius := ParaRadius;

   mFixtureDefinition := Tb2FixtureDef.Create;
   mFixtureDefinition.shape := mCircle;
   mFixtureDefinition.density := 1;
   mFixtureDefinition.friction := 0;
   mFixtureDefinition.restitution := 1.0;

   mBody := ParaWorld.CreateBody( mBodyDefinition, False );
   mFixture := mBody.CreateFixture( mFixtureDefinition, false, false, true );


plus destructor:
Code:

destructor TBall.Destroy;
begin
   mBody.Free;
   mFixtureDefinition.Free;
   mCircle.Free;

   inherited Destroy;
end;


Bye,
Skybuck.


Last edited by Skybuck on Wed Aug 25, 2010 2:17 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sun Aug 22, 2010 8:13 pm 
Offline

Joined: Mon Aug 16, 2010 11:09 am
Posts: 128
To answer my own question, yes... according to the manual, fixtures are automatically cleaned up when the body is destroyed, and fixtures could be destroyed manually to get rid of shapes of bodies I guess.. to pretend that some parts of the body are destroyed.

"
This creates the fixture and attaches it to the body. You do not need to store the fixture pointer since the fixture will automatically be destroyed when the parent body is destroyed. You can create multiple fixtures on a single body.

You can destroy a fixture on the parent body. You may do this to model a breakable object. Otherwise you can just leave the fixture alone and let the body destruction take care of destroying the attached fixtures.
"

Bye,
Skybuck.


Top
 Profile  
 
PostPosted: Wed Aug 25, 2010 10:30 am 
Offline

Joined: Tue Dec 01, 2009 6:33 am
Posts: 15
You give a very good analysis. You don't need to worry about memory leak because box2D cares all things for you. The only thing you need to do is to create DEF objects and pass them as parameter to box2D functions. You don't need to write free lines for them. Because delphi doesn't support stack objects so you need to create the DEF objects. You may ask why not use record for DEF objects. Because I don't know how to initialize them.
As to why there is a parameter called AutoResetMassData. One body can have many shapes fixed, and you can only create one shape with one CreateFixture call. So if you set AutoResetMassData to true(as default), box2D will calculate mass of the body every time you invoke CreateFixture. And you can call ResetMassData when you finish adding shapes to a body. Or you can let AutoResetMassData be true when you are adding the last shape to the body.


Top
 Profile  
 
PostPosted: Wed Aug 25, 2010 10:34 am 
Offline

Joined: Tue Dec 01, 2009 6:33 am
Posts: 15
And one more thing, you don't need to destroy bodies of a world manually. You just call mWorld.Free and every body, joint, shape in this world will be destroyed. It is not recommended to destroy a body by Body.Free when the physics is active. You'd better use World.DestroyBody(Body) instead. Though either way is OK for memory and for logic but the second way is recomended.

The default destructor for Tb2Body is like this
destructor Tb2Body.Destroy;
begin
if Assigned(m_world) then
m_world.DestroyBody(Self, False);
end;
So Body.Free is OK because it actually calls DestroyBody to destroy itself. And last lines of DestroyBody procedure is
if DoFree then
body.Destroy2;
I use DoFree to avoid twice Free for body.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group