Skip to content

Instantly share code, notes, and snippets.

@tfmoraes
Created July 26, 2024 01:27
Show Gist options
  • Save tfmoraes/09e496a3c7084cfc6a2ca33a1254cb98 to your computer and use it in GitHub Desktop.
Save tfmoraes/09e496a3c7084cfc6a2ca33a1254cb98 to your computer and use it in GitHub Desktop.
viewport_overlay.py
import sys
from typing import Optional
import numpy as np
from PySide6.Qt3DCore import Qt3DCore
from PySide6.Qt3DExtras import Qt3DExtras
from PySide6.Qt3DRender import Qt3DRender
from PySide6.QtCore import QPoint, QPointF, QRectF, QSize, QUrl
from PySide6.QtGui import QColor, QFont, QGuiApplication, QPainter, QVector3D
class MyPaintTexture(Qt3DRender.QPaintedTextureImage):
def __init__(self, parent: Optional[Qt3DCore.QNode] = None):
super().__init__(parent)
def paint(self, painter: QPainter) -> None:
print("paint", self.size())
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceOver)
painter.setBackground(QColor(0, 0, 0, 0))
painter.eraseRect(0, 0, self.width(), self.height())
painter.setPen(QColor(255, 255, 255, 255))
painter.setBrush(QColor(255, 255, 255, 255))
painter.setFont(QFont("Decorative", 32))
painter.drawText(QPoint(70, 70), "Manolo")
painter.setPen(QColor(255, 255, 0, 255))
painter.setBrush(QColor(255, 0, 0, 128))
painter.drawEllipse(QPointF(120, 120), 420, 420)
class Window(Qt3DExtras.Qt3DWindow):
def __init__(self):
super().__init__()
# self.camera().lens().setPerspectiveProjection(45, 16 / 9, 0.1, 1000)
# self.camera().setPosition(QVector3D(0, 0, 40))
# self.camera().setViewCenter(QVector3D(0, 0, 0))
self.rootEntity = Qt3DCore.QEntity()
self.rootEntity.setObjectName("rootEntity")
self.setRootEntity(self.rootEntity)
self.render_surface_selector = Qt3DRender.QRenderSurfaceSelector(self.rootEntity)
self.render_surface_selector.setSurface(self.rootEntity)
# self.root_clear_buffer = Qt3DRender.QClearBuffers(self.rootEntity)
# self.root_clear_buffer.setBuffers(Qt3DRender.QClearBuffers.BufferType.AllBuffers)
# self.root_clear_buffer.setClearColor(QColor(255, 255, 255, 255))
self.setActiveFrameGraph(self.render_surface_selector)
# self.renderSettings().setRenderPolicy(Qt3DRender.QRenderSettings.RenderPolicy.Always)
# self.renderStateSet = Qt3DRender.QRenderStateSet(self.rootEntity)
# self._blend_state = Qt3DRender.QBlendEquationArguments()
# self._blend_state.setSourceRgb(Qt3DRender.QBlendEquationArguments.Blending.SourceAlpha)
# self._blend_state.setDestinationRgb(Qt3DRender.QBlendEquationArguments.Blending.OneMinusSourceAlpha)
# self._blend_state.setSourceAlpha(Qt3DRender.QBlendEquationArguments.Blending.One)
# self._blend_state.setDestinationAlpha(Qt3DRender.QBlendEquationArguments.Blending.OneMinusSourceAlpha)
# self._blend_equation = Qt3DRender.QBlendEquation()
# self._blend_equation.setBlendFunction(Qt3DRender.QBlendEquation.BlendFunction.Add)
# self.renderStateSet.addRenderState(self._blend_equation)
# self._depth_test = Qt3DRender.QDepthTest()
# self._depth_test.setDepthFunction(Qt3DRender.QDepthTest.DepthFunction.Less)
# self.renderStateSet.addRenderState(self._depth_test)
print(self.activeFrameGraph())
self.construct_viewport_scene(self.rootEntity)
self.construct_viewport_overlay(self.rootEntity)
self.scene_viewport.setParent(self.activeFrameGraph())
self.overlay_viewport.setParent(self.activeFrameGraph())
# self._no_depht = Qt3DRender.QNoDepthMask()
# self.renderStateSet.addRenderState(self._no_depht)
# # Teste de profundidade
# self.depthTest = Qt3DRender.QDepthTest()
# self.depthTest.setDepthFunction(Qt3DRender.QDepthTest.DepthFunction.LessOrEqual)
# self.renderStateSet.addRenderState(self.depthTest)
#
# Função de blending
# self.blendFunction = Qt3DRender.QBlendEquation()
# self.blendFunction.setBlendFunction(Qt3DRender.QBlendEquation.BlendFunction.)
# self.blendFunction.setDestinationRgb(QBlendFunction.OneMinusSourceAlpha)
# self.renderStateSet.addRenderState(blendFunction)
# self.render_settings = Qt3DRender.QRenderSettings()
# self.render_settings.setRenderPolicy(Qt3DRender.QRenderSettings.RenderPolicy.Always)
# self.render_settings.setActiveFrameGraph(self.activeFrameGraph())
# self.rootEntity.addComponent(self.render_settings)
# self.camera().viewMatrixChanged.connect(self.pmchanged)
self.defaultFrameGraph().setClearColor(QColor(235, 241, 252))
self.create_plane_canvas(self.overlay_entity)
self.create_cube(self.scene_entity)
self.create_sphere(self.scene_entity)
self.create_mesh_from_file(self.scene_entity)
# self.create_textbox(self.overlay_entity)
# print(self.rootEntity.dumpObjectTree())
# print(self.overlay_entity.dumpObjectTree())
self.widthChanged.connect(self.OnSize)
self.heightChanged.connect(self.OnSize)
self.overlay_camera.viewAll()
self.scene_camera.viewAll()
def construct_viewport_scene(self, parent):
self.scene_viewport = Qt3DRender.QViewport()
self.scene_viewport.setObjectName("scene_viewport")
# self.scene_viewport.setNormalizedRect(QRectF(0, 0, 0.5, 1.0))
self.scene_entity = Qt3DCore.QEntity(parent)
self.scene_entity.setObjectName("scene_entity")
self.scene_entity.setEnabled(True)
self.scene_layer = Qt3DRender.QLayer()
self.scene_layer.setRecursive(True)
self.scene_entity.addComponent(self.scene_layer)
self.scene_layer_filter = Qt3DRender.QLayerFilter(self.scene_viewport)
self.scene_layer_filter.addLayer(self.scene_layer)
self.scene_layer_filter.setFilterMode(Qt3DRender.QLayerFilter.FilterMode.AcceptAnyMatchingLayers)
self.scene_camera = Qt3DRender.QCamera(self.scene_entity)
self.scene_camera.lens().setPerspectiveProjection(45, 16 / 9, 0.1, 1000)
self.scene_camera.setPosition(QVector3D(0, 0, 50))
self.scene_camera.setViewCenter(QVector3D(0, 0, 0))
self.scene_camera_selector = Qt3DRender.QCameraSelector(self.scene_layer_filter)
self.scene_camera_selector.setCamera(self.scene_camera)
self.scene_camera_controller = Qt3DExtras.QOrbitCameraController(self.scene_entity)
self.scene_camera_controller.setCamera(self.scene_camera)
self.scene_sort_policy = Qt3DRender.QSortPolicy(self.scene_camera_selector)
self.scene_sort_policy.setSortTypes(
[
Qt3DRender.QSortPolicy.SortType.BackToFront,
]
)
# self.scene_clear_buffer = Qt3DRender.QClearBuffers(self.scene_sort_policy)
# self.scene_clear_buffer.setBuffers(Qt3DRender.QClearBuffers.BufferType.ColorDepthBuffer)
# self.scene_clear_buffer.setClearDepthValue(1.0)
# self.scene_clear_buffer.setClearColor(QColor(255, 255, 255, 0))
self.scene_render_state_set = Qt3DRender.QRenderStateSet(self.scene_sort_policy)
self.scene_blend_state = Qt3DRender.QBlendEquationArguments()
self.scene_blend_state.setSourceRgb(Qt3DRender.QBlendEquationArguments.Blending.SourceAlpha)
self.scene_blend_state.setDestinationRgb(Qt3DRender.QBlendEquationArguments.Blending.OneMinusSourceAlpha)
self.scene_blend_state.setSourceAlpha(Qt3DRender.QBlendEquationArguments.Blending.One)
self.scene_blend_state.setDestinationAlpha(Qt3DRender.QBlendEquationArguments.Blending.OneMinusSourceAlpha)
self.scene_blend_equation = Qt3DRender.QBlendEquation()
self.scene_blend_equation.setBlendFunction(Qt3DRender.QBlendEquation.BlendFunction.Subtract)
self.scene_depth_test = Qt3DRender.QDepthTest()
self.scene_depth_test.setDepthFunction(Qt3DRender.QDepthTest.DepthFunction.LessOrEqual)
self.scene_render_state_set.addRenderState(self.scene_blend_equation)
self.scene_render_state_set.addRenderState(self.scene_depth_test)
self.scene_render_state_set.addRenderState(self.scene_blend_state)
self.scene_render_setting = Qt3DRender.QRenderSettings()
self.scene_render_setting.setActiveFrameGraph(self.scene_render_state_set)
self.scene_entity.addComponent(self.scene_layer)
# self.scene_entity.addComponent(self.scene_render_setting)
def construct_viewport_overlay(self, parent):
self.overlay_viewport = Qt3DRender.QViewport()
self.overlay_viewport.setObjectName("overlay_viewport")
# self.overlay_viewport.setNormalizedRect(QRectF(0.5, 0.0, 1.0, 1.0))
self.overlay_entity = Qt3DCore.QEntity(parent)
self.overlay_entity.setObjectName("overlay_entity")
self.overlay_entity.setEnabled(True)
self.overlay_layer = Qt3DRender.QLayer()
self.overlay_layer.setRecursive(True)
self.overlay_entity.addComponent(self.overlay_layer)
self.overlay_layer_filter = Qt3DRender.QLayerFilter(self.overlay_viewport)
self.overlay_layer_filter.addLayer(self.overlay_layer)
self.overlay_layer_filter.setFilterMode(Qt3DRender.QLayerFilter.FilterMode.AcceptAnyMatchingLayers)
self.overlay_camera = Qt3DRender.QCamera(self.overlay_entity)
self.overlay_camera.setProjectionType(Qt3DRender.QCameraLens.ProjectionType.OrthographicProjection)
self.overlay_camera.lens().setOrthographicProjection(-1, 1, -1, 1, -1000, 1000)
self.overlay_camera.setPosition(QVector3D(0, 0, 100))
self.overlay_camera.setViewCenter(QVector3D(0, 0, 0))
self.overlay_camera.setUpVector(QVector3D(0, 1, 0))
self.overlay_camera.setObjectName("overlay_camera")
self.overlay_camera_selector = Qt3DRender.QCameraSelector(self.overlay_layer_filter)
self.overlay_camera_selector.setCamera(self.overlay_camera)
# self.depth_state = Qt3DRender.QDepthTest()
# self.depth_state.setDepthFunction(Qt3DRender.QDepthTest.DepthFunction.Always)
#
# self.render_state = Qt3DRender.QRenderStateSet(self.overlay_camera_selector)
# self.render_state.addRenderState(self.depth_state)
self.overlay_sort_policy = Qt3DRender.QSortPolicy(self.overlay_camera_selector)
self.overlay_sort_policy.setSortTypes(
[
Qt3DRender.QSortPolicy.SortType.BackToFront,
]
)
# self.overlay_clear_buffer = Qt3DRender.QClearBuffers(self.overlay_sort_policy)
# self.overlay_clear_buffer.setBuffers(Qt3DRender.QClearBuffers.BufferType.DepthBuffer)
# self.overlay_clear_buffer.setClearDepthValue(0.0)
# self.overlay_clear_buffer.setClearColor(QColor(0, 0, 0, 0))
self.overlay_render_state_set = Qt3DRender.QRenderStateSet(self.overlay_sort_policy)
self.overlay_blend_state = Qt3DRender.QBlendEquationArguments()
self.overlay_blend_state.setSourceRgb(Qt3DRender.QBlendEquationArguments.Blending.SourceAlpha)
self.overlay_blend_state.setDestinationRgb(Qt3DRender.QBlendEquationArguments.Blending.OneMinusSourceAlpha)
self.overlay_blend_state.setSourceAlpha(Qt3DRender.QBlendEquationArguments.Blending.One)
self.overlay_blend_state.setDestinationAlpha(Qt3DRender.QBlendEquationArguments.Blending.OneMinusSourceAlpha)
self.overlay_blend_equation = Qt3DRender.QBlendEquation()
self.overlay_blend_equation.setBlendFunction(Qt3DRender.QBlendEquation.BlendFunction.Add)
self.overlay_depth_test = Qt3DRender.QDepthTest()
self.overlay_depth_test.setDepthFunction(Qt3DRender.QDepthTest.DepthFunction.Always)
self.overlay_render_state_set.addRenderState(self.overlay_blend_equation)
self.overlay_render_state_set.addRenderState(self.overlay_depth_test)
self.overlay_render_state_set.addRenderState(self.overlay_blend_state)
# self.overlay_render_setting = Qt3DRender.QRenderSettings()
# self.overlay_render_setting.setActiveFrameGraph(self.overlay_render_state_set)
self.overlay_entity.addComponent(self.overlay_layer)
# self.overlay_entity.addComponent(self.overlay_render_setting)
def create_sphere(self, parent):
sphere_entity = Qt3DCore.QEntity(parent)
sphere = Qt3DExtras.QSphereMesh(sphere_entity)
sphere.setRadius(15)
transform = Qt3DCore.QTransform(sphere_entity)
material = Qt3DExtras.QDiffuseSpecularMaterial(sphere_entity)
material.setDiffuse(QColor(0, 0, 200, 150))
material.setAmbient(QColor(0, 0, 200, 150))
material.setAlphaBlendingEnabled(True)
sphere_entity.addComponent(sphere)
sphere_entity.addComponent(transform)
sphere_entity.addComponent(material)
# sphere_entity.addComponent(self.overlay_layer)
def create_mesh_from_file(self, parent):
mesh_entity = Qt3DCore.QEntity(parent)
mesh = Qt3DRender.QMesh(mesh_entity)
mesh.setSource(QUrl.fromLocalFile(sys.argv[-1]))
mesh.geometryChanged.connect(self.geometry_changed)
mesh_transform = Qt3DCore.QTransform(mesh_entity)
mesh_material = Qt3DExtras.QDiffuseSpecularMaterial(mesh_entity)
mesh_material.setDiffuse(QColor(0, 0, 200, 150))
mesh_material.setAmbient(QColor(0, 0, 200, 150))
mesh_material.setAlphaBlendingEnabled(True)
mesh_entity.addComponent(mesh)
mesh_entity.addComponent(mesh_transform)
mesh_entity.addComponent(mesh_material)
def geometry_changed(self, geometry: Qt3DCore.QGeometry):
for at in geometry.attributes():
if at.name() == Qt3DCore.QAttribute.defaultPositionAttributeName():
geometry.setBoundingVolumePositionAttribute(at)
vertices = np.frombuffer(at.buffer().data().data(), dtype=np.float32, offset=at.byteOffset()).reshape(
-1, 3
)
vertices = np.lib.stride_tricks.as_strided(
vertices, (at.count(), at.vertexSize()), [at.byteStride(), vertices.strides[1]]
)
min_x, min_y, min_z = vertices.min(0)
max_x, max_y, max_z = vertices.max(0)
print(min_x, min_y, min_z)
print(max_x, max_y, max_z)
break
print(geometry.boundingVolumePositionAttribute())
print("Geometry changed", geometry.minExtent(), geometry.maxExtent())
self.scene_camera.viewAll()
def create_cube(self, parent):
cube_entity = Qt3DCore.QEntity(parent)
cube = Qt3DExtras.QCuboidMesh(cube_entity)
cube.setXExtent(13)
cube.setYExtent(5)
cube.setZExtent(44)
transform = Qt3DCore.QTransform(cube_entity)
material = Qt3DExtras.QPhongMaterial(cube_entity)
material.setAmbient("red")
# material.setDiffuse("white")
cube_entity.addComponent(cube)
cube_entity.addComponent(transform)
cube_entity.addComponent(material)
# cube_entity.addComponent(self.scene_layer)
def create_textbox(self, parent):
text_entity = Qt3DCore.QEntity(parent)
text_mesh = Qt3DExtras.QExtrudedTextMesh(text_entity)
font = QFont("Monospace", 120)
text_mesh.setText("Manolo")
text_mesh.setDepth(1.0)
text_mesh.setFont(font)
transform = Qt3DCore.QTransform(text_entity)
transform.setScale(120)
material = Qt3DExtras.QPhongMaterial(text_entity)
material.setAmbient("white")
text_entity.addComponent(transform)
text_entity.addComponent(text_mesh)
text_entity.addComponent(material)
def create_plane_canvas(self, parent):
plane_entity = Qt3DCore.QEntity(parent)
plane_mesh = Qt3DExtras.QPlaneMesh(plane_entity)
plane_mesh.setHeight(2.0)
plane_mesh.setWidth(2.0)
plane_material = Qt3DExtras.QTextureMaterial(plane_entity)
plane_material.setAlphaBlendingEnabled(True)
plane_texture = Qt3DRender.QTexture2D(plane_material)
plane_image = MyPaintTexture(plane_entity)
plane_image.setSize(QSize(self.geometry().width(), self.geometry().height()))
plane_image.update()
plane_texture.setFormat(Qt3DRender.QAbstractTexture.TextureFormat.RGBA8_UNorm)
plane_texture.addTextureImage(plane_image)
plane_material.setTexture(plane_texture)
print(">>.", plane_image.size())
plane_transform = Qt3DCore.QTransform(plane_entity)
plane_transform.setRotationX(90)
plane_entity.addComponent(plane_mesh)
plane_entity.addComponent(plane_material)
plane_entity.addComponent(plane_transform)
plane_image.update()
self.plane_image = plane_image
def OnSize(self, value: int) -> None:
window_width = self.width()
window_height = self.height()
self.scene_camera.lens().setPerspectiveProjection(
45, window_width / window_height, self.scene_camera.lens().nearPlane(), self.scene_camera.lens().farPlane()
)
self.overlay_camera.lens().setOrthographicProjection(
-1,
1,
-1,
1,
self.overlay_camera.lens().nearPlane(),
self.overlay_camera.lens().farPlane(),
)
self.plane_image.setSize(QSize(self.geometry().width(), self.geometry().height()))
self.plane_image.update()
def pmchanged(self):
print(1, self.camera().viewMatrix())
print(2, self.overlay_camera.viewMatrix())
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
view = Window()
view.show()
sys.exit(app.exec())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment