Dyn4j ray cast performance test - 10000 rays

Posts that don't fit into other categories.
chancellor14
Posts: 36
Joined: Sun Sep 14, 2014 8:05 am

Dyn4j ray cast performance test - 10000 rays

Postby chancellor14 » Mon May 25, 2015 3:54 pm

I was curious to see how well dyn4j would perform compared with the box2d stress test video on youtube here: https://youtu.be/C-ScURIRTGA. This video shows a box2d app running with 10,000 rays and achieving an average cast time of 0.003 ms per cast and a maximum of 0.004 ms per cast. This was on a Core 2 Duo 3Ghz processor according to the post.

I wrote a little test program (see below) and ran it with 10,000 rays to see how it compared with the box2d video. The environment I built is less complicated (I got bored with adding shapes :roll: ), but when it runs it gets very similar results to box2d. I get an average of 0.0025 ms per cast and a maximum of 0.0045 ms running on a Quad Core 2.4Ghz processor.

Curiosity satisfied! Just thought I'd post this in case anyone was interested. :geek:

dyn4j ray test.png
Screen shot of ray cast test programme
dyn4j ray test.png (188.44 KiB) Viewed 4648 times


TestLightRays.java
Ray cast Test using dyn4j and Slick2D
(17.02 KiB) Downloaded 162 times

Note the programme uses Slick2d (build 237 with LWJGL 2.9.0).

zoom
Posts: 145
Joined: Sun Mar 17, 2013 3:57 pm
Location: Stockholm, Sweden
Contact:

Re: Dyn4j ray cast performance test - 10000 rays

Postby zoom » Tue May 26, 2015 7:09 am

Cool stuff :)

William
Site Admin
Posts: 378
Joined: Sat Feb 06, 2010 10:23 pm

Re: Dyn4j ray cast performance test - 10000 rays

Postby William » Tue May 26, 2015 4:23 pm

Nice work! These types of comparisons are very useful, not only to those looking to use the library, but also for me to know where to focus effort.

Just for completeness, a more accurate comparison would require the environment to be exactly the same (raycasts against the world are dependent on the number of bodies in the world for example). I wouldn't expect too much of a difference and I definitely understand not wanting to recreate all those shapes... ;)

William

chancellor14
Posts: 36
Joined: Sun Sep 14, 2014 8:05 am

Re: Dyn4j ray cast performance test - 10000 rays

Postby chancellor14 » Wed May 27, 2015 2:42 pm

Great, well I'm glad it's helpful. That makes sense about the bodies - if I get frustrated with my game again and need a diversion (which is regularly at the moment!) then I'll add some more bodies in and see what happens.

Just one quick question about the physics; I've added the bodies and they don't interact, i.e. the light source body just passes over the others. I've updated the code with a collision listener and attached this to the world (this prints out a debug line in each of the 4 methods), but nothing happens. I'm not clear on the settings that make a body collidable or not. I've included the code below that I use to create the bodies. Note I have tried setMass() and setMass(Mass.Type.INFINITE), but not sure if either of these would make the difference. Can you point out where I'm going wrong?

Code: Select all

    private Body buildBody(float maxX, float maxY, byte type) {
        BodyFixture topFixture = null;
        switch (type) {
            case TRIANGLE:
                Vector2 v1 = new Vector2(0, 0);                     // Set up verticies, CCW winding ...
                Vector2 v2 = new Vector2(maxX, maxY / 2);           // using local co-ordinates
                Vector2 v3 = new Vector2(0, maxY);
                Triangle triShape = new Triangle(v1, v2, v3);
                topFixture = new BodyFixture(triShape);
                break;

            case CIRCLE:
                Circle circle = new Circle(maxX);
                topFixture = new BodyFixture(circle);
                break;

            case RECTANGLE:
                Rectangle re = new Rectangle(maxX, maxY);
                topFixture = new BodyFixture(re);
                break;

        }
        topFixture.setDensity(1.0);
        topFixture.createMass();
        topFixture.setSensor(false);                        // React to collisions, don't just sense them
        topFixture.setFilter(Filter.DEFAULT_FILTER);

        Body body = new Body();                             // Create body and...
        body.addFixture(topFixture);                        // ... add triangle to it
//        body.setMass(Mass.Type.INFINTE);                   // Don't let it move
        body.setMass();
        body.setGravityScale(0.0d);
        body.setLinearDamping(999d);                        // Viscosity of environment
        body.setAngularDamping(999d);                       // Prevent rotation through physical interactions
        body.setAutoSleepingEnabled(true);
        body.setActive(true);
        return body;
    }


Here is the CollisionListener code for completeness:

Code: Select all

private final class CollisionListen implements CollisionListener {

    private CollisionListen() {}

    @Override                                               // Broadphase collision detection
    public boolean collision(Body body1, Body body2) {
System.out.println("Boom 1");
        return true;
    }

    @Override                                               // Narrow phase collision detection
    public boolean collision(Body body1, BodyFixture fixture1, Body body2, BodyFixture fixture2, Penetration penetration) {
System.out.println("Boom 2");
        return true;
    }

    @Override                                               // Contact manifold created by the manifold solver
    public boolean collision(Body body1, BodyFixture fixture1, Body body2, BodyFixture fixture2, Manifold manifold) {
System.out.println("Boom 3");
        return true;                                       
    }

    @Override                                               // Contact constraint created
    public boolean collision(ContactConstraint contactConstraint) {
System.out.println("Boom 4");
        return true;                                       
    }
}

William
Site Admin
Posts: 378
Joined: Sat Feb 06, 2010 10:23 pm

Re: Dyn4j ray cast performance test - 10000 rays

Postby William » Wed May 27, 2015 4:59 pm

chancellor14 wrote:Just one quick question about the physics; I've added the bodies and they don't interact, i.e. the light source body just passes over the others. I've updated the code with a collision listener and attached this to the world (this prints out a debug line in each of the 4 methods), but nothing happens.

Are you saying you don't get anything in the console?

You should only need the following:

Code: Select all

// added "massType" parameter
// pass Mass.Type.NORMAL when you want a body that moves (your light source body)
// pass Mass.Type.INFINITE when you want a body that doesn't move (everything else)
private Body buildBody(float maxX, float maxY, byte type, Mass.Type massType) {
        BodyFixture topFixture = null;
        switch (type) {
            case TRIANGLE:
                Vector2 v1 = new Vector2(0, 0);
                Vector2 v2 = new Vector2(maxX, maxY / 2);
                Vector2 v3 = new Vector2(0, maxY);
                Triangle triShape = new Triangle(v1, v2, v3);
                topFixture = new BodyFixture(triShape);
                break;
            case CIRCLE:
                Circle circle = new Circle(maxX);
                topFixture = new BodyFixture(circle);
                break;
            case RECTANGLE:
                Rectangle re = new Rectangle(maxX, maxY);
                topFixture = new BodyFixture(re);
                break;
        }

        Body body = new Body();
        body.addFixture(topFixture);
        body.setMass(massType);
        return body;
}

NOTE: dyn4j doesn't allow collision between infinite mass bodies (it just skips these pairs).

Another thing to check is your update method. It looks like you need to cast delta to a double:

Code: Select all

// code in question:
// world.updatev(delta / 1000);

// not too big of a deal
double d = 2156483 / 1000 = 2156.0
// a big deal
double d = 200 / 1000 = 0.0
// better
double d = (double)2156483 / 1000d = 2156.483
double d = (double)200 / 1000d = 0.2

If delta is less than 1000 the will world will never update because you are passing 0 as the elapsed time (an therefore no collisions will occur).

If you want to control the body like it was controlled in the box2d one, you'll need to use the MouseJoint.

Code: Select all

MouseJoint mj = new MouseJoint(source, new Vector2(0,0), 4.0, 0.7, 1000.0);
// then on each frame, instead of translating the source update the mouse
// joint's target position
mj.setTarget(new Vector2(1, 1));


William

chancellor14
Posts: 36
Joined: Sun Sep 14, 2014 8:05 am

Re: Dyn4j ray cast performance test - 10000 rays

Postby chancellor14 » Thu May 28, 2015 2:20 am

Garn. Casting is the bane of my life! You won't be surprised to learn this isn't the first time I have done this... :cry:

I have also changed the body creation as you suggested. I am now getting output from the console - lots of booms. However, the source isn't interacting with the bodies. I had assumed (maybe wrongly) that dyn4j would automatically deal with the interactions and the source would bounce off the targets. It still jut goes through them. I have tried this with or without the collision listener and it does the same thing. Am I just misunderstanding and do I need to deal with this myself in the collision listener?

In terms of the movement, I have tracked the mouse movements using Slick2D and am updating the source location using body.translate(). The movement works fine, but it occurs to me now that that might be the thing stopping the body interaction I was expecting... is that possibly the case?

Sorry for being such a noob!

zoom
Posts: 145
Joined: Sun Mar 17, 2013 3:57 pm
Location: Stockholm, Sweden
Contact:

Re: Dyn4j ray cast performance test - 10000 rays

Postby zoom » Thu May 28, 2015 4:06 am

I had assumed (maybe wrongly) that dyn4j would automatically deal with the interactions and the source would bounce off the targets.


You assumed right, they should bounce 'by default'. Things that could prevent this is for example all bodies have infinite mass or collision filters prevent collisions.

chancellor14
Posts: 36
Joined: Sun Sep 14, 2014 8:05 am

Re: Dyn4j ray cast performance test - 10000 rays

Postby chancellor14 » Thu May 28, 2015 9:31 am

Thanks zoom. All, but one, of the bodies is set to Mass.Type.INFINITE (i.e. all of the "target" objects). The source object (emitting the rays) is set to Mass.Type.NORMAL. I haven't set any filters so assume (another assumption!) they should all have the default value...

Having re-read William's last post I suspect that using body.translate() to move the source is the thing that is causing the problem. I shall have a play with it over the next few days and try to implement William's suggested method instead.

zoom
Posts: 145
Joined: Sun Mar 17, 2013 3:57 pm
Location: Stockholm, Sweden
Contact:

Re: Dyn4j ray cast performance test - 10000 rays

Postby zoom » Fri May 29, 2015 3:10 am

William is usually right, for obvious reasons :-) I can only shout encouragement to not give up, it is bound to be something simple. In my little game I create bodies, give them an impulse and they bounce around like mad, no extra tricks required.

William
Site Admin
Posts: 378
Joined: Sat Feb 06, 2010 10:23 pm

Re: Dyn4j ray cast performance test - 10000 rays

Postby William » Fri May 29, 2015 10:45 am

The problem is that translating (teleporting) a body doesn't effect it's momentum. In other words, the body is not moving because its velocity is zero and as such, the body is being put to sleep. Asleep bodies, unless in contact with non-asleep bodies will be skipped during collision resolution (the part that makes them not overlap).

You can make this work if you set the Body to not participate in auto-sleeping.

Code: Select all

body.setAutoSleepingEnabled(false);

But I don't recommend directly translating/rotating bodies if you want something physically accurate (you'll run into all sorts of oddities like this). Instead I'd go with applying forces/torques/impulses like zoom said or using a MouseJoint.

William


Return to “General Discussion”

Who is online

Users browsing this forum: No registered users and 1 guest