I am trying to draw colliders of Box2D. Now I have only physics in this example without graphics for simplicity. The DrawSegment()
method must be called to print hello
:
DebugDrawer.cpp
#include "DebugDrawer.h"
#include <QtCore/QDebug>
DebugDrawer::DebugDrawer()
{
}
void DebugDrawer::DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color)
{
qDebug() << "hello";
}
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) { }
I inherited the DebugDrawer
class from the b2Draw
class:
DebugDrawer.h
#ifndef DEBUGDRAWER_H
#define DEBUGDRAWER_H
#include "box2d/b2_draw.h"
class DebugDrawer : public b2Draw
{
public:
DebugDrawer();
private:
// virtual void DrawSegment(b2Vec2& p1, b2Vec2& p2, b2Color& color) override;
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
I created one object with the box shape. I have the animationLoop()
method that I call with timer. Inside of the animationLoop()
method I the m_pWorld->Step()
method and I call the paintGL()
method by calling the update()
method. Inside of the paintGL()
method I call the m_pWorld->DebugDraw()
method. I expect that the DebugDrawer::DrawSegment()
will be called but it does not happen.
Widget.cpp
#include "Widget.h"
#include <QtCore/QDebug>
Widget::Widget(QWidget *parent)
: QOpenGLWidget(parent)
{
setWindowTitle("Box2D, OpenGL3, Qt6, C ");
setFixedSize(QSize(500, 500));
b2Vec2 gravity(0.f, 9.8f);
m_pWorld = new b2World(gravity);
}
Widget::~Widget()
{
delete m_pWorld;
delete m_pDebugDrawer;
}
void Widget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.2f, 0.2f, 0.2f, 1.f);
glEnable(GL_DEPTH_TEST);
m_pDebugDrawer = new DebugDrawer();
m_pWorld->SetDebugDraw(m_pDebugDrawer);
uint32 flags = 0;
flags = b2Draw::e_shapeBit;
flags = b2Draw::e_jointBit;
flags = b2Draw::e_centerOfMassBit;
flags = b2Draw::e_aabbBit;
flags = b2Draw::e_pairBit;
m_pDebugDrawer->SetFlags(flags);
// m_pDebugDrawer->SetFlags(b2Draw::e_shapeBit);
b2PolygonShape shape;
shape.SetAsBox(50.f / WORLD_SCALE, 50.f / WORLD_SCALE);
b2BodyDef bdef;
bdef.type = b2_staticBody;
m_pBody = m_pWorld->CreateBody(&bdef);
m_pBody->CreateFixture(&shape, 2.f);
connect(&m_timer, &QTimer::timeout, this, &Widget::animationLoop);
m_timer.start(1000.f/60.f);
m_elapsedTimer.start();
}
void Widget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_pWorld->DebugDraw();
}
void Widget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void Widget::animationLoop()
{
m_deltaTime = m_elapsedTimer.elapsed() / 1000.f;
m_elapsedTimer.restart();
m_pWorld->Step(m_deltaTime, 8, 3);
update();
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include "box2d/box2d.h"
#include <QtCore/QElapsedTimer>
#include <QtCore/QTimer>
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QtGui/QOpenGLFunctions>
#include "DebugDrawer.h"
class Widget : public QOpenGLWidget, QOpenGLFunctions
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void animationLoop();
private:
void initializeGL() override;
void paintGL() override;
void resizeGL(int w, int h) override;
private:
const float WORLD_SCALE = 30.f;
b2World *m_pWorld;
DebugDrawer *m_pDebugDrawer;
b2Body *m_pBody;
QElapsedTimer m_elapsedTimer;
QTimer m_timer;
float m_deltaTime;
};
#endif // WIDGET_H
main.cpp
#ifdef _WIN32
#include <windows.h>
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
#endif
#include <QtGui/QSurfaceFormat>
#include <QtWidgets/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSurfaceFormat format;
format.setSamples(8);
Widget w;
w.setFormat(format);
w.show();
return a.exec();
}
.pro
QT = core gui openglwidgets
win32: LIBS = -lopengl32
INCLUDEPATH = "E:\Libs\box2d-2.4.1-mingw-64-bit\include"
LIBS = -L"E:\Libs\box2d-2.4.1-mingw-64-bit\lib"
LIBS = -lbox2d
greaterThan(QT_MAJOR_VERSION, 4): QT = widgets
CONFIG = c 11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES = QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES = \
DebugDrawer.cpp \
main.cpp \
Widget.cpp
HEADERS = \
DebugDrawer.h \
Widget.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS = target
CodePudding user response:
The DrawSegment
method is not called because there is no Box2D's objects that must be drawn with segments. I add b2EdgeShape
in the physics world and now DrawSegment
works:
b2EdgeShape edgeShape;
edgeShape.SetOneSided(b2Vec2(0.f, 0.f), b2Vec2(1.f, 0.f),
b2Vec2(2.f, 0.f), b2Vec2(3.f, 0.f));
m_pEdgeBody = m_pWorld->CreateBody(&bdef);
m_pEdgeBody->CreateFixture(&edgeShape, 2.f);