Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. How to use the Box2D's b2Draw class in PyQt6 with OpenGL3? DrawSegment is not called
Forum Updated to NodeBB v4.3 + New Features

How to use the Box2D's b2Draw class in PyQt6 with OpenGL3? DrawSegment is not called

Scheduled Pinned Locked Moved Solved Game Development
11 Posts 2 Posters 1.5k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #2

    Hi,

    From a quick look at the repo, and if I understood correctly your question, it seems you would need to call SetDebugDraw from the b2World class to make use of your class.

    However there's a bug opened about that method so it's not really clear if it's possible.

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    8Observer88 1 Reply Last reply
    0
    • SGaistS SGaist

      Hi,

      From a quick look at the repo, and if I understood correctly your question, it seems you would need to call SetDebugDraw from the b2World class to make use of your class.

      However there's a bug opened about that method so it's not really clear if it's possible.

      8Observer88 Offline
      8Observer88 Offline
      8Observer8
      wrote on last edited by 8Observer8
      #3

      @SGaist said in How to use the Box2D's b2Draw class in PyQt6 with OpenGL3? DrawSegment is not called:

      However there's a bug opened about that method so it's not really clear if it's possible.

      This issue was opened by me. There is self.world.renderer = self.debugDrawer instead of self.world.SetDebugDraw(self.debugDrawer).

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #4

        These are python bindings, so setting render like that might not work unless there is explicit support for that through the bindings.

        You can add new attributes to python objects but that does not mean it will translate to the underlying C++ object.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • 8Observer88 Offline
          8Observer88 Offline
          8Observer8
          wrote on last edited by 8Observer8
          #5

          This property exists in IntelliSense:

          93d5b8ff-7d60-4034-8f15-321f324e188d-image.png

          At first I found it in the documentation: https://github.com/pybox2d/pybox2d/wiki/manual#drawing

          You can see there this example of usage:

          draw = MyDraw()
          world = b2World()
          world.renderer = draw
          

          DrawPolygon() works in my example. It prints hello:

          from Box2D import b2Draw
          
          
          class DebugDrawer(b2Draw):
          
              def DrawSegment(self, p1, p2, color):
                  print("hello")
          
              def DrawPolygon(self, vertices, color):
                  print("hello")
          
              def DrawSolidPolygon(self, vertices, color):
                  pass
              def DrawPoint(self, p, size, color):
                  pass
              def DrawCircle(self, center, radius, color, drawwidth=1):
                  pass
              def DrawSolidCircle(self, center, radius, axis, color):
                  pass
              def DrawTransform(self, xf):
                  pass
          

          But DrawSegment does not work and I do not understand why.

          1 Reply Last reply
          0
          • 8Observer88 Offline
            8Observer88 Offline
            8Observer8
            wrote on last edited by 8Observer8
            #6

            I can print polygons like this:

            class DebugDrawer(b2Draw):
            
                def DrawSegment(self, p1, p2, color):
                    print("hello")
            
                def DrawPolygon(self, vertices, color):
                    print("Polygon. Begin")
                    print(vertices[0][0] * 30, vertices[0][1] * 30)
                    print(vertices[1][0] * 30, vertices[1][1] * 30)
                    print(vertices[2][0] * 30, vertices[2][1] * 30)
                    print(vertices[3][0] * 30, vertices[3][1] * 30)
                    print("Polygon. End")
            

            Output:

            Polygon. Begin
            -53.29999923706055 -53.29999923706055
            53.29999923706055 -53.29999923706055
            53.29999923706055 53.29999923706055
            -53.29999923706055 53.29999923706055
            Polygon. End
            

            But I need segments. Why DrawSegment does not work?

            1 Reply Last reply
            0
            • 8Observer88 Offline
              8Observer88 Offline
              8Observer8
              wrote on last edited by
              #7

              Temporary I can get segments from polygon.

              1 Reply Last reply
              0
              • 8Observer88 Offline
                8Observer88 Offline
                8Observer8
                wrote on last edited by 8Observer8
                #8

                I have to use DrawPolygon to draw collider segments when I use blocks to draw borders around gameobjects. DrawSegment() will be called when b2EdgeShape is instantiated:

                        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)
                
                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #9

                  Glad you found out and thanks for sharing !

                  It would be nice a have a complete example that shows how to use a debug drawer provided by Box2D. Did you consider submitting one ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  8Observer88 1 Reply Last reply
                  1
                  • SGaistS SGaist

                    Glad you found out and thanks for sharing !

                    It would be nice a have a complete example that shows how to use a debug drawer provided by Box2D. Did you consider submitting one ?

                    8Observer88 Offline
                    8Observer88 Offline
                    8Observer8
                    wrote on last edited by 8Observer8
                    #10

                    @SGaist said in How to use the Box2D's b2Draw class in PyQt6 with OpenGL3? DrawSegment is not called:

                    It would be nice a have a complete example that shows how to use a debug drawer provided by Box2D. Did you consider submitting one ?

                    I wrote this simple example using OpenGL version 1 for simplicity:

                    debug-drawer-opengl1-pyqt6.gif

                    PyBox2D currently works at most with Python version 3.8, as written on GitHub:

                    Recent builds should be available for Windows, Linux, and OS X, with Python 3.6, 3.7, and 3.8.

                    You must have PyQt6, PyOpenGL, and PyBox2D installed to run this example:

                    pip install PyQt6 PyOpenGL Box2D

                    main.py

                    import sys
                    
                    from PyQt6.QtCore import Qt
                    from PyQt6.QtGui import QSurfaceFormat
                    from PyQt6.QtWidgets import QApplication
                    
                    from opengl_widget import OpenGLWidget
                    
                    
                    def main():
                        QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL)
                        app = QApplication(sys.argv)
                    
                        format = QSurfaceFormat()
                        format.setSamples(8)
                    
                        w = OpenGLWidget()
                        w.setFormat(format)
                        w.show()
                        sys.exit(app.exec())
                    
                    if __name__ == "__main__":
                        main()
                    

                    opengl_widget.py

                    import math
                    
                    from Box2D import (b2_dynamicBody, b2_staticBody, b2Body, b2BodyDef,
                                       b2FixtureDef, b2PolygonShape, b2Vec2, b2World)
                    from OpenGL.GL import *
                    from PyQt6.QtCore import QElapsedTimer, QSize, QTimer
                    from PyQt6.QtOpenGLWidgets import QOpenGLWidget
                    
                    from debug_drawer import DebugDrawer
                    
                    
                    class OpenGLWidget(QOpenGLWidget):
                    
                        def __init__(self):
                            super().__init__()
                            self.setWindowTitle("Box2D, OpenGL1, PyQt6")
                            self.setFixedSize(QSize(400, 400))
                            self.deltaTime = 0
                    
                            self.WORLD_SCALE = 30.0
                            self.world = b2World(gravity=b2Vec2(0.0, -9.8))
                    
                        def initializeGL(self):
                            glClearColor(0.2, 0.2, 0.2, 1.0)
                    
                            self.debugDrawer = DebugDrawer()
                            self.world.renderer = self.debugDrawer
                    
                            self.debugDrawer.flags = { 'drawShapes': True,
                                'drawJoints': True, 'drawAABBs': True, 'drawPairs': True }
                            # print(self.debugDrawer.flags)
                    
                            boxShape = b2PolygonShape()
                            boxShape.SetAsBox(10 / self.WORLD_SCALE, 10 / self.WORLD_SCALE)
                            boxBodyDef = b2BodyDef()
                            boxBodyDef.type = b2_dynamicBody
                            self.boxBody = self.world.CreateBody(boxBodyDef)
                            boxFixtureDef = b2FixtureDef()
                            boxFixtureDef.shape = boxShape
                            boxFixtureDef.density = 2
                            self.boxBody.CreateFixture(boxFixtureDef)
                            self.boxBody.position = b2Vec2(100 / self.WORLD_SCALE, 100 / self.WORLD_SCALE)
                    
                            groundShape = b2PolygonShape()
                            groundShape.SetAsBox(100 / self.WORLD_SCALE, 10 / self.WORLD_SCALE)
                            groundBodyDef = b2BodyDef()
                            groundBodyDef.type = b2_staticBody
                            groundBody = self.world.CreateBody(groundBodyDef)
                            groundFixtureDef = b2FixtureDef()
                            groundFixtureDef.shape = groundShape
                            groundFixtureDef.density = 2
                            groundBody.CreateFixture(groundFixtureDef)
                            groundBody.position = b2Vec2(100 / self.WORLD_SCALE, 0 / self.WORLD_SCALE)
                    
                            platformShape = b2PolygonShape()
                            platformShape.SetAsBox(30 / self.WORLD_SCALE, 5 / self.WORLD_SCALE)
                            platformBodyDef = b2BodyDef()
                            platformBodyDef.type = b2_staticBody
                            platformBody = self.world.CreateBody(platformBodyDef)
                            platformFixtureDef = b2FixtureDef()
                            platformFixtureDef.shape = platformShape
                            boxFixtureDef.density = 2
                            platformBody.CreateFixture(platformFixtureDef)
                            platformBody.position = b2Vec2(100 / self.WORLD_SCALE, 50 / self.WORLD_SCALE)
                            platformBody.angle = math.radians(-10)
                    
                            self.timer = QTimer()
                            self.timer.timeout.connect(self.animationLoop)
                            self.elapsedTimer = QElapsedTimer()
                            self.elapsedTimer.start()
                            self.timer.start(1000//60)
                    
                        def paintGL(self):
                            glClear(GL_COLOR_BUFFER_BIT)
                            self.world.DrawDebugData()
                    
                        def resizeGL(self, w, h):
                            glViewport(0, 0, w, h)
                            glMatrixMode(GL_PROJECTION)
                            glLoadIdentity()
                            glOrtho(0, 200, 0, 200, -10, 10)
                    
                        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
                    from OpenGL.GL import *
                    
                    
                    class DebugDrawer(b2Draw):
                    
                        def DrawSolidPolygon(self, vertexes, color):
                            # print("Polygon. Begin")
                            # print(vertexes[0][0] * 30, vertexes[0][1] * 30)
                            # print(vertexes[1][0] * 30, vertexes[1][1] * 30)
                            # print(vertexes[2][0] * 30, vertexes[2][1] * 30)
                            # print(vertexes[3][0] * 30, vertexes[3][1] * 30)
                            # print("Polygon. End")
                    
                            glLineWidth(3)
                    
                            glBegin(GL_LINES)
                            glColor3f(color.r, color.g, color.b)
                    
                            glVertex2f(vertexes[0][0] * 30, vertexes[0][1] * 30)
                            glVertex2f(vertexes[1][0] * 30, vertexes[1][1] * 30)
                    
                            glVertex2f(vertexes[1][0] * 30, vertexes[1][1] * 30)
                            glVertex2f(vertexes[2][0] * 30, vertexes[2][1] * 30)
                    
                            glVertex2f(vertexes[2][0] * 30, vertexes[2][1] * 30)
                            glVertex2f(vertexes[3][0] * 30, vertexes[3][1] * 30)
                            
                            glVertex2f(vertexes[3][0] * 30, vertexes[3][1] * 30)
                            glVertex2f(vertexes[0][0] * 30, vertexes[0][1] * 30)
                            glEnd()
                    
                        def DrawPolygon(self, vertexes, color):
                            pass
                        def DrawSegment(self, p1, p2, color):
                            pass
                        def DrawPoint(self, p, size, color):
                            pass
                        def DrawCircle(self, center, radius, color, drawwidth=1):
                            pass
                        def DrawSolidCircle(self, center, radius, axis, color):
                            pass
                        def DrawTransform(self, xf):
                            pass
                    
                    1 Reply Last reply
                    1
                    • 8Observer88 Offline
                      8Observer88 Offline
                      8Observer8
                      wrote on last edited by
                      #11

                      Added restart button:

                      edit-gravity-debug-drawer-opengl1-pyqt6.gif

                      Source code: https://github.com/8Observer8/edit-gravity-debug-drawer-opengl1-pyqt6

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved