Created
July 26, 2024 01:27
-
-
Save tfmoraes/09e496a3c7084cfc6a2ca33a1254cb98 to your computer and use it in GitHub Desktop.
viewport_overlay.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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