如何在SDL2中使用b2Draw?DrawSegment方法未被调用
问题:Box2D中DebugDrawer的DrawSegment方法未被调用
我期望控制台输出hello,但重载的DrawSegment方法始终没被触发,相关代码如下:
DebugDrawer.cpp
#include "DebugDrawer.h" #include <iostream> DebugDrawer::DebugDrawer() { } void DebugDrawer::DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color) { std::cout << "hello" << std::endl; } void DebugDrawer::DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color) { } void DebugDrawer::DrawPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color) { } void DebugDrawer::DrawPoint(const b2Vec2 &p, float size, const b2Color &color) { } void DebugDrawer::DrawCircle(const b2Vec2 ¢er, float radius, const b2Color &color) { } void DebugDrawer::DrawSolidCircle(const b2Vec2 ¢er, float radius, const b2Vec2 &axis, const b2Color &color) { } void DebugDrawer::DrawTransform(const b2Transform &xf) { }
DebugDrawer.h
#ifndef DEBUGDRAWER_H #define DEBUGDRAWER_H #include "box2d/b2_draw.h" class DebugDrawer : public b2Draw { public: DebugDrawer(); private: void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color); void DrawPoint (const b2Vec2 &p, float size, const b2Color &color); void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color); void DrawCircle(const b2Vec2& center, float radius, const b2Color& color); void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color); void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color); void DrawTransform(const b2Transform& xf); }; #endif // DEBUGDRAWER_H
创建矩形物体代码
b2PolygonShape shape; shape.SetAsBox(50.f / WORLD_SCALE, 50.f / WORLD_SCALE); b2BodyDef bdef; bdef.type = b2_staticBody; pBody = pWorld->CreateBody(&bdef); pBody->CreateFixture(&shape, 2.f);
调试绘制设置(main.cpp中)
pDebugDrawer = new DebugDrawer(); pWorld->SetDebugDraw(pDebugDrawer); uint32 flags = 0; flags += b2Draw::e_shapeBit; flags += b2Draw::e_jointBit; flags += b2Draw::e_centerOfMassBit; flags += b2Draw::e_aabbBit; flags += b2Draw::e_pairBit; pDebugDrawer->SetFlags(flags);
主循环中的调用
pWorld->Step(0.016f, 8, 3); pWorld->DebugDraw();
完整main.cpp
#ifdef _WIN32 #include <windows.h> extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; #endif #define SDL_MAIN_HANDLED #include <glad/glad.h> #include <SDL.h> #include <box2d/box2d.h> #include <iostream> #include "DebugDrawer.h" const float WORLD_SCALE = 30.f; b2World* pWorld; DebugDrawer* pDebugDrawer; b2Body* pBody; int main() { // Initialize the SDL2 library if (SDL_Init(SDL_INIT_VIDEO) != 0) { SDL_Log("Failed to initialize the SDL2 library: %s", SDL_GetError()); return 1; } // Create a SDL window const int WIN_WIDTH = 500; const int WIN_HEIGHT = 500; SDL_Window* window = SDL_CreateWindow( "Empty Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); // Create a SDL renderer SDL_Renderer* renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED); if (!renderer) { SDL_Log("Failed to create a SDL renderer %s", SDL_GetError()); return 1; } SDL_GLContext context = SDL_GL_CreateContext(window); // Initialize the GLAD library if (!gladLoadGL()) { SDL_Log("Failed to initialize the GLAD library"); return 1; } glViewport(0, 0, WIN_WIDTH, WIN_HEIGHT); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); b2Vec2 gravity(0.f, 9.8f); pWorld = new b2World(gravity); pDebugDrawer = new DebugDrawer(); pWorld->SetDebugDraw(pDebugDrawer); uint32 flags = 0; flags += b2Draw::e_shapeBit; flags += b2Draw::e_jointBit; flags += b2Draw::e_centerOfMassBit; flags += b2Draw::e_aabbBit; flags += b2Draw::e_pairBit; pDebugDrawer->SetFlags(flags); b2PolygonShape shape; shape.SetAsBox(50.f / WORLD_SCALE, 50.f / WORLD_SCALE); b2BodyDef bdef; bdef.type = b2_staticBody; pBody = pWorld->CreateBody(&bdef); pBody->CreateFixture(&shape, 2.f); SDL_Event event; bool running = true; SDL_PollEvent(&event); while (running) { switch (event.type) { case SDL_QUIT: running = false; break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: running = false; break; } break; } glClear(GL_COLOR_BUFFER_BIT); pWorld->Step(0.016f, 8, 3); pWorld->DebugDraw(); SDL_GL_SwapWindow(window); SDL_PollEvent(&event); } delete pWorld; delete pDebugDrawer; SDL_GL_DeleteContext(context); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
解决方案
1. 修正方法的访问权限
b2Draw基类中的所有绘制方法都是public虚函数,但你在子类中把DrawSegment等方法设为了private。基类调用这些方法时无法访问子类的私有实现,实际执行的是基类的空方法,而非你写的输出逻辑。
修改DebugDrawer.h,将所有重载方法改为public,并加上override关键字确保重载正确:
class DebugDrawer : public b2Draw { public: DebugDrawer(); void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override; void DrawPoint (const b2Vec2 &p, float size, const b2Color &color) override; void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override; void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override; void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override; void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override; void DrawTransform(const b2Transform& xf) override; };
2. 触发DrawSegment的场景说明
DrawSegment不会在绘制普通静态多边形时被调用,它的触发场景包括:
- 启用
e_jointBit时,绘制关节的连接线 - 启用
e_pairBit时,绘制碰撞对的重叠部分 - 手动在其他绘制方法中调用
DrawSegment
如果需要测试DrawSegment,可以添加两个物体并创建关节,或者在DrawPolygon中遍历多边形顶点调用DrawSegment绘制边。
3. 验证物体是否在视口内
虽然你的静态物体默认在原点,但可以确认世界坐标转屏幕坐标的逻辑是否正确,确保物体处于视口范围内,否则调试绘制可能不会触发。
内容的提问来源于stack exchange,提问作者8Observer8
相关产品推荐
相关产品推荐

