Box2D C++ tutorials - Using debug draw


Last edited: July 31 2011 
Using debug draw
The testbed makes use of a feature known as "debug draw" to draw the shapes you see. Obviously if you are making a game you will want to have all kinds of eye-popping fancy graphics instead of these boring polygons, but the debug draw feature can be very useful when you are having trouble getting the physics scene to work right. Sometimes the problem can be in the rendering part of your game, for example a sprite may be drawn at the wrong position or rotation, giving the appearance of incorrect physics. I recommend keeping the debug draw ready to hand for times when you want to check exactly what is going on in the Box2D world.

“debug draw”能够利用一些特征,来画你所看到的形状(这样我们就能形象的看到我们代码所画的图形了),显然如果你正在制作一个游戏,你一定会非常希望自己有一个全视角的图形界面而不是那些令人讨厌的多边形。然而debug deaw可能是非常有用的当你让这物理的界面去正常工作的时候,有时候这些问题可能是出现在游戏渲染的一部分而不是代码部分,例如一个精灵可能被画在了错误的位置或者角度,给出了不适当的物理出现方式,我建议保持debugdeaw 在你每次运行的时候 当你想要准确的检查box2d世界正在进行什么的时候。这样你就能发现代码之外你绘图方面的一些不足之处。


The way it works is quite simple. Box2D tells you all the shapes it sees and where they are eg. "a circle of radius r at x,y", or "an edge from a to b", etc and you draw what you are told. You don't have to do any transforming or worry about where the actual body positions are or which fixtures belong to which bodies, you simply draw the geometry. The idea is that if all you have to do is draw a few lines, you can't mess it up :-)

他的工作方式是非常简单的 box2d会告诉你所有的形状就像我们看到的那样和他们所在的位置。例如 一个圆半径r画在点x,y,或者一个边从a到b,等等。并且你可以画出那些你被告诉的形状。你不需要去做任何翻译或者担心那些body的准确位置或者这个fixtures属于那个bodys,你只需要仅仅简单的画几何的形状。我的意思是说如果你要做的仅仅是画一些线,你根本不可能把他搞乱。

The default debug draw used by the testbed is done by subclassing the b2DebugDraw class, which has a bunch of virtual functions that can be overridden. Here are the main players: 

通常情况下debugdraw 被用来进行测试,这个debugdraw是b2DebugDraw class的子类,b2DebugDraw class有一个虚函数的聚合那个可以在你的子类中被重写,这里是一些主要的成员函数;

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;


Separating the rendering code into one location like this makes it easy to implement debug drawing for different APIs like DirectX or OpenGL ES, or switch between different methods easily.

如果不去涉及代码部分的渲染部分,那么上面的代码是非常容易实现的,不同的api接口例如direxts或者opengles,或者简单的在两者之间进行转换。


Although the testbed's default debug draw works just fine and we don't really need to customize it, since we're on the topic let's try using our own subclass to alter the appearance a bit. Any scene from the previous topics will be ok to use - I'll start with the same scene as for the moving at constant speed topic.

尽管测试台默认的debugdraw工作起来是正常的并且我们没有必要去对它函数的定义进行重写,由于我们的主题是debugdraw所以让我们尝试着去使用我们自己的子类去为做一个能够提示的系统。 任何前面的代码显示的场景我们都能够使用,这里我使用了和moving at constant speed 主题一样的景设定。

To make our own debug draw class, we will need to implement all of the pure virtual functions. For now let's just make them all empty: 

做我们自己的debugdraw类,我们需要实例化所有的纯虚函数,现在我们写上这些函数的一个空体(定义部分没有实现只是函数的生命)从这里可以看到foodraw类继承自b2DebugDraw继承方法是公用继承。

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

To tell the Box2D world to use this class instead of the default one, we use the SetDebugDraw function. This function takes a pointer to a b2DebugDraw object, so we'll need to have an instance of the class to point to. This is easily done by just declaring a variable of your new class at global scope. 

告诉box2d世界,我们用我们自己制作的类而不是默认提供的那个,我们使用SetDebugDraw函数,这个函数有一个指向b2DebugDraw类实例的指针作为参数,所以我们需要一个这个类的实例然后让指针指向它,使用我们的类声明一个全局变量,这是非常容易做到的。

 //at global scope
FooDraw fooDrawInstance;

//in constructor, usually
m_world->SetDebugDraw( &fooDrawInstance );

//somewhere appropriate
fooDrawInstance.SetFlags( b2DebugDraw::e_shapeBit );
This will tell the world what class instance it should direct all the drawing instructions to. Notice the last part which selects a certain category of debug information to display. Right now we are interested in seeing the shapes (fixtures) in the world, but you can also set this flag to include the following: 

这些将会告诉世界哪一个类的实例将要按照指定的绘图命令去绘图,注意最后一部分它使用了一个确定的部分(属于debug 信息 去展示陈列),现在我们非常的想要看一下形状和fixture在这box2d的世界里面,但是你也可以设置这flag去包含下面的部分。

e_shapeBit ( draw shapes )
e_jointBit ( draw joint connections
e_aabbBit ( draw axis aligned bounding boxes )
e_pairBit ( draw broad-phase pairs )
e_centerOfMassBit ( draw a marker at body CoM )
e_shapeBit ( draw shapes ) 
e_jointBit ( draw joint connections
e_aabbBit ( draw axis aligned bounding boxes )
e_pairBit ( draw broad-phase pairs )
e_centerOfMassBit ( draw a marker at body CoM )

I say to put this setting 'somewhere appropriate' because it's something you might want to alter at run time, like in the situation I mentioned above when you might occasionally want to confirm that your rendered game entities and Box2D are doing the same thing. In the testbed, you can see these settings as the checkboxes on the right hand panel.

我说把这些设置放在适合的地方,因为它的一些事情你也许只想在他运行的时候示警,就像我给你提到过的状态,那些只有在你偶尔想要确定一下你渲染的游戏中的物体是什么的时候,并且 box2d会做同样的时候。你可以看到这些设置,就像在你熟悉的操作板上检查一个箱子一样简单


If you use a debug draw class in your own projects, there is one other important point to be aware of: you need to call the DrawDebugData() function of your world, which will in turn cause Box2D to call back to your debug draw class functions for each shape that needs drawing.

如果你在你自己的项目里面使用一个debugdraw,这里有一些事情你必须要注意,你需要在你的世界里面调用DrawDebugData()函数,这个函数会依次轮流的让box2d去调用你debugdraw类里面的韩式为你的每个需要绘制的形状


Running the testbed now you should see nothing showing in the scene. This is because we still have a completely empty debug draw implementation. From this point, what you fill in the drawing functions depends on what platform and rendering API you are using. As an example, let's implement the DrawSolidPolygon function in OpenGL ES, as used on embedded platforms such as the iPhone. This is a handy example because OpenGL ES is a subset of OpenGL so we can still run it on our PC in the testbed as normal, and also because it's one of those questions that comes up often.

现在运行这测试台 你将能够看到没有任何东西显示在这屏幕上这是因为我们仍然有一个没有被实现的debugdraw类,从这一点开始

函数的定义部分部分的却觉语什么样的平台或者什么样的渲染api你是用的。例如,让我们实现这个DrawSolidPolygon函数在opengles的情况下,经常被用在植入的平台上例如iphone 这是一个容易的例子因为opengles属于opengl的一个子集,所以我们能够运行像平常一样在我们电脑上的测试台上运行他 并且因为这个 


 OpenGL ES does not have the glBegin/glEnd/glVertex functions, so rendering is done with vertex arrays instead: 

opengles没有glBegin/glEnd/glVertex函数 所以我们的渲染要你管vertes数组代替

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

The other drawing functions can be done in much the same way. Depending on what rendering API you are using, circles might have to be drawn as a polygon with many sides.

其他的debugdraw里面的函数可以用同样的方式实现,那个同样取决与你的程序使用的api 圆也许不得不使用一个有很多边的多边形代替



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值