Box2D C++ DebugDraw

来源:互联网 发布:浙江省网络选修课程 编辑:程序博客网 时间:2024/04/26 07:10

~~~~我的生活,我的点点滴滴!!


              http://ohcoder.com/blog/2012/11/30/using-debug-draw/


testbed使用一个称为“debug draw”的特性来画你所见到的形状。不过很显然,如果你想让游戏能够更加吸引眼球,还是需要替换那些

无聊的多边形的,但是当物理场景中产生问题时,debug draw会变的非常有用。有时候问题发生在游戏场景中的某个部分,比如精灵被显

示在错误的位置或错误的旋转方式,产生不正确的物理现象。如果你想准确的检测Box2d世界正在发生什么,那么我建议你保留debug draw

的功能。


它的工作方式非常简单,它会告诉你Box2d中所有的形状以及这些形状的位置等。在x,y位置,半径为r的弧形或者一条从a到b的边
等其他你

所需要的形状。你不必做任何的变换或者担心物体的位置或者哪个定制器属于哪个物体,你可以轻松的画出这些几何形状。这就是说如果

你只会画几条线段,也不会把事情搞砸。


testbed中默认的debug draw由包含一堆虚方法的子类DebugDraw类完成。这里列出主要的方法:


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来实现渲染调试,又或者可以在不同的渲染

方法之间简单的切换。


为了实现自定义的debug draw类,我们需要实现所有纯虚函数。现在先让我们清空这些方法。

class FooDraw : public DebugDraw{    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世界使用此类代替默认的那个。这个方法的参数使用了一个指向DebugDraw对象的指针,所以我

们需要有一个指向此类的对象指针。可以声明一个新的全局变量。

//at global scopeFooDraw fooDrawInstance;//in constructor, usuallym_world->SetDebugDraw( &fooDrawInstance );//somewhere appropriatefooDrawInstance.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方法,所以使用顶点数组代替进行渲染:

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);}


其它渲染方法也可以类比。取决于你所使用的API,圆弧可以使用多个短的线段来渲染。


0 0