Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Objects don't occlude each other as expected #4

Closed
nmevenkamp opened this issue Dec 14, 2019 · 2 comments
Closed

Objects don't occlude each other as expected #4

nmevenkamp opened this issue Dec 14, 2019 · 2 comments

Comments

@nmevenkamp
Copy link
Contributor

nmevenkamp commented Dec 14, 2019

I implemented a small MWE to showcase the issue (see code below).

It creates four cards of random color and places them next to each other (like you would hold them in your hand when playing any kind of card game). Using 8 buttons, you can move the cards forward and backward. I observe the following behaviour: when moving cards from the back to the front, they don't go "through" the adjacent cards. Instead, it seems that the card nearest to the camera on initialization is always rendered on top on the screen, even if it should be behind any of the other cards at some point.

For comparison, you can exchange run_qt() for run_panda3d() at the bottom of the MWE script, which shows that when using plain Panda3D, the cards occlude each other as expected.

Tested on Windows 10, GTX 1070 Ti, Python 3.6.

I'd really appreciate if you could have a look since I was hoping to use this module to migrate the GUI for my card game from Panda's DirectGUI to Qt.

Python source for MWE:
# Standard imports
import sys

# External imports
import numpy as np
from panda3d.core import *


def get_card_node_path(parent) -> NodePath:
    width = 6.35
    height = 8.89
    thickness = 0.529

    dimensions = [width / 2, height / 2, thickness / 2]

    vertex_format = GeomVertexFormat().getV3n3cpt2()
    vertex_data = GeomVertexData("vertex_data", vertex_format, Geom.UHStatic)

    vertexCount = 0

    tris = GeomTriangles(Geom.UHStatic)

    vertex_writer = GeomVertexWriter(vertex_data, "vertex")
    color_writer = GeomVertexWriter(vertex_data, "color")
    normal_writer = GeomVertexWriter(vertex_data, "normal")
    texcoord_writer = GeomVertexWriter(vertex_data, "texcoord")

    for i in range(3):
        for direction in (-1, 1):
            normal = VBase3()
            normal[i] = direction

            if i == 1:
                rgb = [1., 1., 1.]
            else:
                rgb = [np.random.rand(), np.random.rand(), np.random.rand()]

            r, g, b = rgb
            color = (r, g, b, 1.)

            for a, b in ((-1., -1.), (-1., 1.), (1., 1.), (1., -1.)):
                vertex = VBase3()

                vertex[i] = direction * dimensions[i]
                vertex[(i + direction) % 3] = a * dimensions[(i + direction) % 3]
                vertex[(i + direction * 2) % 3] = b * dimensions[(i + direction * 2) % 3]

                vertex_writer.addData3f(vertex)
                color_writer.addData4f(color)
                normal_writer.addData3f(normal)

                if i == 2:
                    if direction == -1:
                        texcoord_writer.addData2f((1 - b) / 4, (a + 1) / 2)
                    else:
                        texcoord_writer.addData2f(0.5 + (a + 1) / 4, (b + 1) / 2)
                else:
                    texcoord_writer.addData2f(0, 0)

            vertexCount += 4

            tris.addVertices(vertexCount - 2, vertexCount - 3, vertexCount - 4)
            tris.addVertices(vertexCount - 4, vertexCount - 1, vertexCount - 2)

    geom = Geom(vertex_data)
    geom.addPrimitive(tris)

    node = GeomNode("geom_node")
    node.addGeom(geom)

    card_np = parent.attachNewNode(node)
    card_np.setPos(0, 0, 0)

    return card_np


def run_qt():
    loadPrcFileData('', 'back-buffers 0')

    from PyQt5 import QtWidgets
    from QPanda3D.Panda3DWorld import Panda3DWorld
    from QPanda3D.QPanda3DWidget import QPanda3DWidget

    app = QtWidgets.QApplication(sys.argv)
    main_window = QtWidgets.QMainWindow()
    main_window.setGeometry(50, 50, 800, 600)

    world = Panda3DWorld()
    panda_widget = QPanda3DWidget(world)

    main_window.setCentralWidget(panda_widget)
    main_window.show()

    # add lights
    ambient_light = AmbientLight('ambient_light')
    ambient_light.setColor(VBase4(1, 1, 1, 1))
    ambient_light_np = world.render.attachNewNode(ambient_light)
    world.render.setLight(ambient_light_np)

    directional_light = DirectionalLight('directional_light')
    directional_light.setColor(VBase4(1, 1, 1, 1))
    directional_light_np = world.camera.attachNewNode(directional_light)
    world.render.setLight(directional_light_np)

    # position camera
    world.camera.setPos(0, -50, 50)
    world.camera.lookAt(0, 0, 0)

    # add cards
    num_cards = 4
    cards = [get_card_node_path(world.render) for _ in range(num_cards)]

    for i, np in enumerate(cards):
        np.setPos(i * 2, 10 - i, -5)
        np.lookAt(np, 0, 0, -1)

    # add GUI
    layout = QtWidgets.QGridLayout()

    widget = QtWidgets.QWidget(parent=panda_widget)

    def move(index, direction):
        np = cards[index]
        np.setPos(np, 0, 0, direction)
        print("Moved card #{}".format(index))

    for index in range(num_cards):
        button = QtWidgets.QPushButton("Move #{} forward".format(index))
        button.clicked.connect(lambda state, x=index: move(x, -1))
        layout.addWidget(button, 1, index)

        button = QtWidgets.QPushButton("Move #{} backwards".format(index))
        button.clicked.connect(lambda state, x=index: move(x, 1))
        layout.addWidget(button, 0, index)

    widget.setLayout(layout)
    widget.show()

    # run
    sys.exit(app.exec_())


def run_panda3d():
    from direct.showbase.ShowBase import ShowBase
    from direct.gui.DirectGui import DirectButton

    base = ShowBase()
    base.disableMouse()

    # add lights
    ambient_light = AmbientLight('ambient_light')
    ambient_light.setColor(VBase4(1, 1, 1, 1))
    ambient_light_np = render.attachNewNode(ambient_light)
    render.setLight(ambient_light_np)

    directional_light = DirectionalLight('directional_light')
    directional_light.setColor(VBase4(1, 1, 1, 1))
    directional_light_np = camera.attachNewNode(directional_light)
    render.setLight(directional_light_np)

    # position camera
    camera.setPos(0, -50, 50)
    camera.lookAt(0, 0, 0)

    # add cards
    num_cards = 4
    cards = [get_card_node_path(render) for _ in range(num_cards)]

    for i, np in enumerate(cards):
        np.setPos(i * 2, 10 - i, -5)
        np.lookAt(np, 0, 0, -1)

    # add GUI
    def move(index, direction):
        np = cards[index]
        np.setPos(np, 0, 0, direction)
        print("Moved card #{}".format(index))

    # Add button
    for index in range(num_cards):
        DirectButton(
            text=("Move #{} backwards".format(index)),
            scale=.05,
            command=lambda x=index: move(x, 1),
            pos=(-0.9 + 0.6 * index, 0, 0.9)
        )
        DirectButton(
            text=("Move #{} forward".format(index)),
            scale=.05,
            command=lambda x=index: move(x, -1),
            pos=(-0.9 + 0.6 * index, 0, 0.8)
        )

    # run
    base.run()


if __name__ == '__main__':
    run_qt()
@nmevenkamp
Copy link
Contributor Author

I found that replacing

props.set_depth_bits(0)

with

props.set_depth_bits(8)

inside __init__ of PandaWorld3D fixes the issue.

Is there any particular reason you set it to zero?

@nmevenkamp
Copy link
Contributor Author

I created a pull request that changes the aforementioned line accordingly.

I also added .idea to the .gitignore which is used as a project settings folder by PyCharm which I am using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant