Open 8Observer8 opened 1 year ago
The same example in PyQt6:
main.py
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QSurfaceFormat
from PyQt6.QtWidgets import QApplication
from widget import Widget
def main():
QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL)
app = QApplication(sys.argv)
format = QSurfaceFormat()
format.setSamples(8)
w = Widget()
w.setFormat(format)
w.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
widget.py
from Box2D import (b2_staticBody, b2Body, b2BodyDef, b2FixtureDef,
b2PolygonShape, b2Vec2, b2World)
from OpenGL import GL as gl
from PyQt6.QtCore import QElapsedTimer, QSize, QTimer
from PyQt6.QtOpenGLWidgets import QOpenGLWidget
from debug_drawer import DebugDrawer
class Widget(QOpenGLWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Box2D, OpenGL3, PyQt6")
self.setFixedSize(QSize(500, 500))
self.deltaTime = 0
self.WORLD_SCALE = 30.0
self.world = b2World(gravity=b2Vec2(0.0, 9.8))
def initializeGL(self):
gl.glClearColor(0.2, 0.2, 0.2, 1.0)
gl.glEnable(gl.GL_DEPTH_TEST)
self.debugDrawer = DebugDrawer()
self.world.renderer = self.debugDrawer
self.debugDrawer.flags = { 'drawShapes': True,
'drawJoints': True, 'drawAABBs': True, 'drawPairs': True }
# print(self.debugDrawer.flags)
shape = b2PolygonShape()
shape.SetAsBox(50.0 / self.WORLD_SCALE, 50.0 / self.WORLD_SCALE)
bodyDef = b2BodyDef()
bodyDef.type = b2_staticBody
self.body: b2Body = self.world.CreateBody(bodyDef)
fixtureDef = b2FixtureDef()
fixtureDef.shape = shape
fixtureDef.density = 2
self.body.CreateFixture(fixtureDef)
self.timer = QTimer()
self.timer.timeout.connect(self.animationLoop)
self.elapsedTimer = QElapsedTimer()
self.elapsedTimer.start()
self.timer.start(1000//60)
def paintGL(self):
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
self.world.DrawDebugData()
def resizeGL(self, w: int, h: int):
gl.glViewport(0, 0, w, h)
def animationLoop(self):
self.deltaTime = self.elapsedTimer.elapsed() / 1000.0
self.elapsedTimer.restart()
self.world.Step(self.deltaTime, 8, 3)
self.update()
debug_drawer.py
from Box2D import b2Draw
class DebugDrawer(b2Draw):
def DrawSegment(self, p1, p2, color):
print("hello")
def DrawSolidPolygon(self, vertices, color):
pass
def DrawPoint(self, p, size, color):
pass
def DrawPolygon(self, vertices, color):
pass
def DrawCircle(self, center, radius, color, drawwidth=1):
pass
def DrawSolidCircle(self, center, radius, axis, color):
pass
def DrawTransform(self, xf):
pass
The same example in Qt6 and C++:
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();
}
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
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();
}
.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
I should use DrawPolygon
to draw segments of colliders when I use boxes to draw borders around game objects. DrawSegment()
will be called when an instance of b2EdgeShape
is created:
C++:
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);
Python:
edgeShape = b2EdgeShape()
edgeShape.vertices = [(0.0, 0.0), (1.0, 0.0)]
self.edgeBody: b2Body = self.world.CreateBody(bodyDef)
edgeFixtureDef = b2FixtureDef()
edgeFixtureDef.shape = edgeShape
edgeFixtureDef.density = 2
self.edgeBody.CreateFixture(edgeFixtureDef)
I already have created three simple examples in: Qt6, PyQt6, and SDL2. I thought that a problem in Qt6 but it the same for three cases. It looks like a bug. These examples try to print
hello
in the console fromDrawSegment()
.I expect to see
hello
in the console:DebugDrawer.cpp
I inherited from the
b2Draw
and overloaded the methods:DebugDrawer.h
I created an object with the box shape:
I set the debug draw in the
main.cpp
file:I set flags:
I call
pWorld.Step()
andpWorld->DebugDraw()
:main.cpp