Box2D C++ 教程-使用debug Draw

轉載文章:原貼地址:http://ohcoder.com/blog/2012/11/30/using-debug-draw/

  • 使用debug draw

testbed使用一個稱爲“debug draw”的特性來畫你所見到的形狀。不過很顯然,如果你想讓遊戲能夠更加吸引眼球,還是需要替換那些無聊的多邊形的,但是當物理場景中產生問題時,debug draw會變的非常有用。有時候問題發生在遊戲場景中的某個部分,比如精靈被顯示在錯誤的位置或錯誤的旋轉方式,產生不正確的物理現象。如果你想準確的檢測Box2d世界正在發生什麼,那麼我建議你保留debug draw的功能。

它的工作方式非常簡單。它會告訴你Box2d中所有的形狀以及這些形狀的位置等。“在x,y位置,半徑爲r的弧形”,或者“一條從a到b的邊”,等其他你所需要的形狀。你不必做任何的變換或者擔心物體的位置或者哪個定製器屬於哪個物體,你可以輕鬆的畫出這些幾何形狀。這就是說如果你只會畫幾條線段,也不會把事情搞砸:-)。

testbed中默認的debug draw由包含一堆虛方法的子類b2DebugDraw類完成。這裏列出主要的方法:

1
2
3
4
5
6
virtual void DrawPolygon(b2Vec2* vertices, int32 vertexCount, b2Color& color) = 0;
virtual void DrawSolidPolygon(b2Vec2* vertices, int32 vertexCount, b2Color& color) = 0;
virtual void DrawCircle(b2Vec2& center, float32 radius, b2Color& color) = 0;
virtual void DrawSolidCircle(b2Vec2& center, float32 radius, b2Vec2& axis, b2Color& color) = 0;
virtual void DrawSegment(b2Vec2& p1, b2Vec2& p2, b2Color& color) = 0;
virtual void DrawTransform(const b2Transform& xf) = 0;

把專門的渲染代碼放到一個獨立的地方,就像用DirectX或者OpenGL ES一樣,輕鬆調用不同API來實現渲染調試,又或者可以在不同的渲染方法之間簡單的切換。

雖然testbed中的debug draw工作的很好,而且我們真的不需要對它進行自定義,但是既然我們在討論這個話題,那麼就讓我們使用我們自定義的子類來做一點改變吧。任何之前所討論話題中的場景都可以進行嘗試-這裏我將會使用勻速運動(moving at constant speed)話題中所討論的場景。

pic

爲了實現自定義的debug draw類,我們需要實現所有純虛函數。現在先讓我們清空這些方法。

1
2
3
4
5
6
7
8
9
10
class FooDraw : public b2DebugDraw
{
    public:
        void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) {}
        void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) {}
        void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) {}
        void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) {}
        void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) {}
        void DrawTransform(const b2Transform& xf) {}
};

我們可以使用SetDebugDraw方法,告訴Box2D世界使用此類代替默認的那個。這個方法的參數使用了一個指向b2DebugDraw對象的指針,所以我們需要有一個指向此類的對象指針。可以聲明一個新的全局變量。

1
2
3
4
5
6
//at global scope
FooDraw fooDrawInstance;
//in constructor, usually
m_world->SetDebugDraw( &fooDrawInstance );
//somewhere appropriate
fooDrawInstance.SetFlags( b2DebugDraw::e_shapeBit );

這樣就可以告訴物理世界所要渲染的任務是有新指定的類對象來完成。注意最後一行代碼中設置的標誌是進行渲染的類型。現在如果你想在查看物理世界時,讓其中的形狀(定製器)變的更有趣,你還需要設置包括如下標誌:

-e_shapeBit(畫形狀(draw shapes)) 
-e_jointBit(畫連接器(draw joint connections)) 
-e_aabbBit(軸對齊包圍盒(draw axis aligned bounding boxes) 
-e_pairBit(畫broad-phase對(draw broad-phase pairs)) 
-e_centerOfMassBit(在物體上標出質心(draw a marker at body CoM))

其實,我的意思是想把這些設置放到一個‘合適的地方’,因爲可能有些設置你想在運行的時候進行設置,就像上面提到的情況,當你偶爾想判斷一下你所渲染的遊戲實體和Box2D是否是同一個事物的時候。在testbed中,你可以看到一些設置放到了右邊選擇面板上。

如果你在自己的項目中使用了debug draw類,有另一個重要的需要注意的點是:你需要在你的物理世界中調用DrawDebugData()方法,這個方法會讓Box2D對所要渲染形狀回調每一個需要調用的debug draw類方法。

現在運行testbed,在場景中你應該什麼也看不到。這是因爲我們仍然沒有實現對應的debug draw方法。從這一點來說,你所實現的渲染方法取決於是什麼平臺以及你所使用的渲染的API。作爲一個例子,讓我們用在嵌入式平臺iPhone上使用OpenGL ES來實現DrawSolidPolygon方法。這是一個靈活的例子,因爲OpenGL ES是OpenGL的一個子集,所以我們也可以在PC平臺的testbed上像普通程序一樣運行,而且跨平臺問題也是我們經常遇到的問題。

OpenGL ES不會有glBegin/glEnd/glVertex方法,所以使用頂點數組代替進行渲染:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
    //set up vertex array
    GLfloat glverts[16]; //allow for polygons up to 8 vertices
    glVertexPointer(2, GL_FLOAT, 0, glverts); //tell OpenGL where to find vertices
    glEnableClientState(GL_VERTEX_ARRAY); //use vertices in subsequent calls to glDrawArrays

    //fill in vertex positions as directed by Box2D
    for (int i = 0; i < vertexCount; i++) {
        glverts[i*2]   = vertices[i].x;
        glverts[i*2+1] = vertices[i].y;
    }

    //draw solid area
    glColor4f( color.r, color.g, color.b, 1);
    glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);

    //draw lines
    glLineWidth(3); //fat lines
    glColor4f( 1, 0, 1, 1 ); //purple
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
}

pic

其它渲染方法也可以類比。取決於你所使用的API,圓弧可以使用多個短的線段來渲染。

更新:我注意到在iPhone上Box2D源代碼中,有一個好的使用OpenGL ES實現debug draw的方法。這是爲Obj-C所寫,但只是使用了普通的C++,所以你可以不用做任何修改:GLES-Render.mm


發佈了36 篇原創文章 · 獲贊 5 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章