A quick question regarding Downhill Supreme

General discussion about the R.U.B.E editor
banarne
Posts: 19
Joined: Fri Aug 23, 2013 1:30 pm

A quick question regarding Downhill Supreme

Post by banarne »

I just bought Downhill Supreme and it's great! Good work!

just a technical question, your performance is great even on older devices (iPod 4). I'm wondering if the performance on older devices drops if you're running the game with debugdraw on?

I just made a rube scene that I exported and it works great on iPhone 5 (both with debugdraw on and off) but on iPod 4 the fps is reduced substantially when debugdraw is enabled (still 60 fps when debugdraw is off).

Is this normal? Did you do any optimizations (besides the ones you did with the ground that you talked about here https://www.iforce2d.net/blog/2013-07-20) just for older devices?

Do you unload/delete any fixtures/bodies from the json after the file's been loaded and the user is playing a level?

Thanks
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: A quick question regarding Downhill Supreme

Post by iforce2d »

iPod4 is old? Yeah I guess it is. I mostly test with iPod3G and iPad1 :D

It depends how much geometry is in the scene, but yes the debug draw can slow things down a bit. In DHS there is not much geometry at all, but on the long levels even the single ground line could slow things enough that it was worth handling it specifically for the track preview (white line at the bottom of the screen). A maximum of 250 segments are drawn for that, which is usually enough to cover as much of the preview as fits on the screen.

It's not so much the number of line segments, but the number of calls into the GPU that can cause slowdowns. The typical debug draw has a DrawSegment function which is used to draw each piece one at a time, but a much preferable way is to put all the vertices in an array and draw them with a single call to glDrawArrays.

No bodies/fixtures are deleted while playing a level, but there are some kinda tricky things happening at load time. Of course some joints are destroyed to detach the rider and bike when he crashes. The sequence of events at load time goes something like this:
1. Load the track .json, then destroy all dynamic bodies. This is done to make sure no bike bodies are there, because the guy making the track needs to have a bike in there to test with, and sometimes he forgets to delete it before the final release. It was easier just to delete dynamic bodies than check all the levels manually to make sure the bike was taken out. Since RUBE now has a command-line interface for batch jobs, this type of thing will not be necessary in future.
2. Load the bike .json (the real one, at a specific location, with correct images etc)
3. Load the rear suspension linkage .json for the frame that the player has chosen.
4. Find joints in the linkage .json with specific names, and placeholder joints in the bike.json with matching names. The joints in the linkage will be altered so that one side (eg. bodyA) of the joint connects to the bike, then the placeholder joints are deleted.

You can see all the gory details about the bike model and what I mean by linkages in this video: http://www.youtube.com/watch?v=bBIXpu-D_Zo
Some more background here: http://www.box2d.org/forum/viewtopic.php?f=6&t=9314
banarne
Posts: 19
Joined: Fri Aug 23, 2013 1:30 pm

Re: A quick question regarding Downhill Supreme

Post by banarne »

iforce2d wrote: It's not so much the number of line segments, but the number of calls into the GPU that can cause slowdowns. The typical debug draw has a DrawSegment function which is used to draw each piece one at a time, but a much preferable way is to put all the vertices in an array and draw them with a single call to glDrawArrays.
This sounds great. Where is it suitable to put the vertices in an array? How would you recommend that I update my draw method? I'm basing this on the loader that you supplied, using cocos2d. Was DHS made using cocos2d/rube?

my current draw method:

Code: Select all

-(void) draw
{
    if ( !m_world )
        return;
    
    [super draw];
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
    
    kmGLPushMatrix();
	m_world->DrawDebugData();

    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;
    //flags += b2Draw::e_jointBit;
    //flags += b2Draw::e_aabbBit;
    //flags += b2Draw::e_pairBit;
    //flags += b2Draw::e_centerOfMassBit;
    m_debugDraw->SetFlags(flags);
    
    kmGLPopMatrix();

    
}
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: A quick question regarding Downhill Supreme

Post by iforce2d »

Yes, DHS was made with Cocos2d and RUBE :)
fwiw this is the function that draws the preview line:

Code: Select all

//global variable
static float trackPreviewLineVertices[4 * 250]; // 2 vertices per segment = 4 floats

void drawChainFixture_inAABB(b2Fixture* fixture, b2AABB& aabb)
{
    if ( fixture->GetType() != b2Shape::e_chain )
        return;
    
    b2ChainShape* chain = (b2ChainShape*)fixture->GetShape();
    int32 count = chain->m_count;
    const b2Vec2* vertices = chain->m_vertices;
    
    int numLinesPlaced = 0;

    const b2Transform& xf = fixture->GetBody()->GetTransform();
    b2Vec2 v1 = b2Mul(xf, vertices[0]);
    for (int32 i = 1; i < count; ++i)
    {
        b2Vec2 v2 = b2Mul(xf, vertices[i]);
        if ( v2.x > aabb.lowerBound.x ) {
            trackPreviewLineVertices[4 * numLinesPlaced + 0] = v1.x;
            trackPreviewLineVertices[4 * numLinesPlaced + 1] = v1.y;
            trackPreviewLineVertices[4 * numLinesPlaced + 2] = v2.x;
            trackPreviewLineVertices[4 * numLinesPlaced + 3] = v2.y;
            numLinesPlaced += 1;
        }
        v1 = v2;
        if ( numLinesPlaced >= 250 || v1.x > aabb.upperBound.x )
            break;
    }
    
    if ( numLinesPlaced > 0 ) {
        glVertexPointer(2, GL_FLOAT, 0, trackPreviewLineVertices);
        glDrawArrays(GL_LINES, 0, numLinesPlaced * 2);
    }
}
The AABB is the current view bounds visible on screen. As you can see the storage for the vertices is a fixed size, so it is allocated in global scope and never needs to change. Although the function is given an AABB, it only uses the x-coords, because the track is mostly horizontal - this might not work for your case. I also know that the chain shape starts with the first vertex on the left, and goes toward the right. So I can loop over all vertices of the chain in order, and if the vertex is within the horizontal bounds of the screen, put it in the array to be drawn, up to a maximum of 250. Then draw the array. This is using OpenGL 1.1
banarne
Posts: 19
Joined: Fri Aug 23, 2013 1:30 pm

Re: A quick question regarding Downhill Supreme

Post by banarne »

cool, thanks.

I'm using OpenGL ES 2.0 in cocos2d 2.x. I thought that I would be able to replace:

glVertexPointer
with
glVertexAttribPointer

but no luck :(

glDrawArrays doesn't get me any compile errors, but theoretically this should work for opengl es 2.0, yes?

The ground-line that you're using in DHS is a line shape with a radius of 0 (in RUBE), correct? I got a little confused when you started talking about chain shape, but perhaps I'm not down with the lingo :O :)
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: A quick question regarding Downhill Supreme

Post by iforce2d »

The only thing I know about OpenGL ES 2.0 is that it takes a lot of work to draw something very simple :D Maybe somebody else can help with that.

About the line, yes it's a 'line' shape type in RUBE, which gets output as a b2ChainShape in the exported .json.
vkreal
Posts: 66
Joined: Sun Jan 13, 2013 7:29 pm

Re: A quick question regarding Downhill Supreme

Post by vkreal »

here's what i use to draw terrain from RUBE in opengl 2

glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, _hillVertices);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, _hillTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)_nHillVertices);
banarne
Posts: 19
Joined: Fri Aug 23, 2013 1:30 pm

Re: A quick question regarding Downhill Supreme

Post by banarne »

great, thanks guys!

EDIT:

vkreal how did you dump your vertices to hillVertices and hillTexCoords? did you save them as ccVertex2F?
ifMike
Posts: 6
Joined: Mon Sep 02, 2013 9:53 am

Re: A quick question regarding Downhill Supreme

Post by ifMike »

banarne wrote: vkreal how did you dump your vertices to hillVertices and hillTexCoords? did you save them as ccVertex2F?
This is exactly what I am trying to do - just posted in another thread https://www.iforce2d.net/forums/viewtop ... rt=10#p925
vkreal
Posts: 66
Joined: Sun Jan 13, 2013 7:29 pm

Re: A quick question regarding Downhill Supreme

Post by vkreal »

banarne wrote:great, thanks guys!

EDIT:

vkreal how did you dump your vertices to hillVertices and hillTexCoords? did you save them as ccVertex2F?
I just did same as Ray's tutorial explains about applying textures under a sine curve. instead of sine i just use vertices from RUBE. You just want draw visible section for good fps. It should be explained how in Ray's tut
Post Reply