diff options
| author | alonrubintec <alonrubintech@gmail.com> | 2023-01-31 23:45:31 +0200 |
|---|---|---|
| committer | alonrubintec <alonrubintech@gmail.com> | 2023-01-31 23:45:31 +0200 |
| commit | b982a82f137f3cf2184bf44d12e18fcc91f1c1ee (patch) | |
| tree | 7dd3fa8f401562a9954b017da45d1bb8541eccfe | |
Initial commit
| -rw-r--r-- | README.md | 39 | ||||
| -rw-r--r-- | arcball.py | 105 | ||||
| -rw-r--r-- | engine.py | 220 | ||||
| -rw-r--r-- | functions.py | 155 | ||||
| -rw-r--r-- | main.py | 67 | ||||
| -rw-r--r-- | resource/3DView02.ui | 1612 | ||||
| -rw-r--r-- | resource/app_preview.PNG | bin | 0 -> 264211 bytes | |||
| -rw-r--r-- | resource/load.png | bin | 0 -> 1582 bytes | |||
| -rw-r--r-- | resource/shaders.py | 47 |
9 files changed, 2245 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..7870222 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +## Qt 3DViewer +### Qt 3DViewer is a compact tool for viewing 3D models in a user friendly way. + +<br>This project is a compact and user-friendly application designed to showcase +<br>3D models in a visually appealing manner. With support for a wide range of +<br>file formats including .obj, .stl, .ply, .off, and .om. + +Powered by Python the PyQt framework, the app use OpenGL, in combination +<br>with ModernGL to render the 3D models and scenes in a interactive experience. +<br>Designed and developed by Alon Rubin. + + + +### Movement: + +- Rotate: click and drag the <b>left mouse</b> button. +- Pan: click and drag the <b>right mouse</b> button. +- Zoom: use the <b>mouse wheel</b> to zoom in or out. + +### Watch a video demo: + +<a href="https://www.youtube.com/watch?v=ZwK2B9AODtw&ab_channel=ALONZUBINA" target="_blank"> +<img src="https://i.ytimg.com/an_webp/ZwK2B9AODtw/mqdefault_6s.webp?du=3000&sqp=CPzh5Z4G&rs=AOn4CLCFIgJwRNM3GbouU5iCmgl1I0AuDw" alt="Watch the series" width="340" height="180" border="10" /> +</a> + +### App preview: + + +### How to install: + +1. Install Python 3.9 +2. Install PyQt 5 +3. Import all the Libraries + +## Like this project? + +Check out other stuff that i make: +<br>https://github.com/alonrubintec +<br>https://www.artstation.com/alonzu diff --git a/arcball.py b/arcball.py new file mode 100644 index 0000000..be6759e --- /dev/null +++ b/arcball.py @@ -0,0 +1,105 @@ +import numpy as np +from scipy.spatial.transform import Rotation as R + + +class ArcBall: + def __init__(self, NewWidth: float, NewHeight: float): + self.StVec = np.zeros(3, 'f4') # Saved click vector + self.EnVec = np.zeros(3, 'f4') # Saved drag vector + self.AdjustWidth = 0. # Mouse bounds width + self.AdjustHeight = 0. # Mouse bounds height + self.setBounds(NewWidth, NewHeight) + self.Epsilon = 1.0e-5 + + def setBounds(self, NewWidth: float, NewHeight: float): + assert((NewWidth > 1.0) and (NewHeight > 1.0)) + # Set adjustment factor for width/height + self.AdjustWidth = 1.0 / ((NewWidth - 1.0) * 0.5) + self.AdjustHeight = 1.0 / ((NewHeight - 1.0) * 0.5) + + def click(self, NewPt): + # Map the point to the sphere + self._mapToSphere(NewPt, self.StVec) + + def drag(self, NewPt): + NewRot = np.zeros((4,), 'f4') + # Map the point to the sphere + self._mapToSphere(NewPt, self.EnVec) + Perp = np.cross(self.StVec, self.EnVec) + # Compute the length of the perpendicular vector + if np.linalg.norm(Perp) > self.Epsilon: # if its non-zero + NewRot[:3] = Perp[:3] + NewRot[3] = np.dot(self.StVec, self.EnVec) + else: + pass + return NewRot + + def _mapToSphere(self, NewPt, NewVec): + TempPt = NewPt.copy() + TempPt[0] = (TempPt[0] * self.AdjustWidth) - 1.0 + TempPt[1] = 1.0 - (TempPt[1] * self.AdjustHeight) + # center + length2 = np.dot(TempPt, TempPt) + if length2 > 1.0: + # Compute a normalizing factor + norm = 1.0 / np.sqrt(length2) + NewVec[0] = TempPt[0] * norm + NewVec[1] = TempPt[1] * norm + NewVec[2] = 0.0 + else: + # Return a vector to a point mapped inside the sphere + NewVec[0] = TempPt[0] + NewVec[1] = TempPt[1] + NewVec[2] = np.sqrt(1.0 - length2) + + +class ArcBallUtil(ArcBall): + def __init__(self, NewWidth: float, NewHeight: float): + self.Transform = np.identity(4, 'f4') + self.LastRot = np.identity(3, 'f4') + self.ThisRot = np.identity(3, 'f4') + self.isDragging = False + super().__init__(NewWidth, NewHeight) + + def onDrag(self, cursor_x, cursor_y): + if self.isDragging: + mouse_pt = np.array([cursor_x, cursor_y], 'f4') + # Update End Vector And Get Rotation As Quaternion + self.ThisQuat = self.drag(mouse_pt) + self.ThisQuat[0] *= 0.5 # Reduce the influence of the vertical axis + self.ThisRot = self.Matrix3fSetRotationFromQuat4f(self.ThisQuat) + self.ThisRot = np.matmul(self.LastRot, self.ThisRot) + self.Transform = self.Matrix4fSetRotationFromMatrix3f( + self.Transform, self.ThisRot) + return + + def resetRotation(self): + self.isDragging = False + self.LastRot = np.identity(3, 'f4') + self.ThisRot = np.identity(3, 'f4') + self.Transform = self.Matrix4fSetRotationFromMatrix3f(self.Transform, + self.ThisRot) + + def onClickLeftUp(self): + self.isDragging = False + # Set Last Static Rotation To Last Dynamic One + self.LastRot = self.ThisRot.copy() + + def onClickLeftDown(self, cursor_x: float, cursor_y: float): + self.LastRot = self.ThisRot.copy() + self.isDragging = True + mouse_pt = np.array([cursor_x, cursor_y], 'f4') + self.click(mouse_pt) + return + + def Matrix4fSetRotationFromMatrix3f(self, NewObj, m3x3): + scale = np.linalg.norm(NewObj[:3, :3], ord='fro') / np.sqrt(3) + NewObj[0:3, 0:3] = m3x3 * scale + scaled_NewObj = NewObj + return scaled_NewObj + + def Matrix3fSetRotationFromQuat4f(self, q1): + if np.sum(np.dot(q1, q1)) < self.Epsilon: + return np.identity(3, 'f4') + r = R.from_quat(q1) + return r.as_matrix().T diff --git a/engine.py b/engine.py new file mode 100644 index 0000000..4ffb1c9 --- /dev/null +++ b/engine.py @@ -0,0 +1,220 @@ +import numpy +import moderngl +import math + +from PyQt5 import QtOpenGL, QtCore +from arcball import ArcBallUtil +from pyrr import Matrix44 +from resource import shaders + + +def grid(size, steps): + # Create grid parameters + u = numpy.repeat(numpy.linspace(-size, size, steps), 2) + v = numpy.tile([-size, size], steps) + w = numpy.zeros(steps * 2) + new_grid = numpy.concatenate([numpy.dstack([u, v, w]), numpy.dstack([v, u, w])]) + + # Rotate grid + lower_grid = 0.135 + rotation_matrix = numpy.array([ + [0, 0, 1], + [1, 0, 0], + [0, lower_grid, 0] + ]) + return numpy.dot(new_grid, rotation_matrix) + + +class QGLControllerWidget(QtOpenGL.QGLWidget): + def __init__(self, parent=None): + self.parent = parent + super(QGLControllerWidget, self).__init__(parent) + + # Initialize OpenGL parameters + self.bg_color = (0.1, 0.1, 0.1, 0.1) + self.color_alpha = 1.0 + self.new_color = (1.0, 1.0, 1.0, self.color_alpha) + self.fov = 60.0 + self.camera_zoom = 2.0 + self.setMouseTracking(True) + self.wheelEvent = self.update_zoom + self.is_wireframe = False + self.texture = None + self.cell = 50 + self.size = 20 + self.grid = grid(self.size, self.cell) + self.grid_alpha_value = 1.0 + + def initializeGL(self): + # Create a new OpenGL context + self.ctx = moderngl.create_context() + + # Create the shader program + self.prog = self.ctx.program( + vertex_shader=shaders.vertex_shader, + fragment_shader=shaders.fragment_shader + ) + self.set_scene() + + def set_scene(self): + # Setting shader parameters + self.light = self.prog['Light'] + self.color = self.prog['Color'] + self.mvp = self.prog['Mvp'] + self.prog["Texture"].value = 0 + self.light.value = (1.0, 1.0, 1.0) + self.color.value = (1.0, 1.0, 1.0, 1.0) + + # Setting mesh parameters + self.mesh = None + self.vbo = self.ctx.buffer(self.grid.astype('f4')) + self.vao2 = self.ctx.simple_vertex_array(self.prog, self.vbo, 'in_position') + + # Setting ArcBall parameters + self.arc_ball = ArcBallUtil(self.width(), self.height()) + self.center = numpy.zeros(3) + self.scale = 1.0 + + def paintGL(self): + # OpenGL loop + self.ctx.clear(*self.bg_color) + self.ctx.enable(moderngl.BLEND) + self.ctx.enable(moderngl.DEPTH_TEST | moderngl.CULL_FACE) + self.ctx.wireframe = self.is_wireframe + if self.mesh is None: + return + + # Update projection matrix loop + self.aspect_ratio = self.width() / max(1.0, self.height()) + proj = Matrix44.perspective_projection(self.fov, self.aspect_ratio, 0.1, 1000.0) + lookat = Matrix44.look_at( + (0.0, 0.0, self.camera_zoom), + (0.0, 0.0, 0.0), + (0.0, 1.0, 0.0), + ) + self.arc_ball.Transform[3, :3] = -self.arc_ball.Transform[:3, :3].T @ self.center + self.mvp.write((proj * lookat * self.arc_ball.Transform).astype('f4')) + + # Render mesh loop + self.color.value = self.new_color + self.vao.render() + + # Render grid loop + self.color.value = (1.0, 1.0, 1.0, self.grid_alpha_value) + self.vao2.render(moderngl.LINES) + self.color.value = self.new_color + + def set_mesh(self, new_mesh): + if new_mesh is None: + self.set_scene() + return + self.mesh = new_mesh + self.mesh.update_normals() + + # Creates an index buffer + index_buffer = self.ctx.buffer(numpy.array(self.mesh.face_vertex_indices(), dtype="u4").tobytes()) + + # Creates a list of vertex buffer objects (VBOs) + vao_content = [(self.ctx.buffer(numpy.array(self.mesh.points(), dtype="f4").tobytes()), '3f', 'in_position'), + (self.ctx.buffer(numpy.array(self.mesh.vertex_normals(), dtype="f4").tobytes()), '3f', 'in_normal')] + self.vao = self.ctx.vertex_array(self.prog, vao_content, index_buffer, 4) + self.init_arcball() + + def init_arcball(self): + # Create ArcBall + self.arc_ball = ArcBallUtil(self.width(), self.height()) + mesh_points = self.mesh.points() + bounding_box_min = numpy.min(mesh_points, axis=0) + bounding_box_max = numpy.max(mesh_points, axis=0) + self.center = 0.5*(bounding_box_max+bounding_box_min) + self.scale = numpy.linalg.norm(bounding_box_max-self.center) + self.arc_ball.Transform[:3, :3] /= self.scale + self.arc_ball.Transform[3, :3] = -self.center/self.scale + + # -------------- GUI interface -------------- + def change_light_color(self, color, alpha=1): + color = color + (alpha,) + print(color) + self.color.value = color + self.new_color = color + + def update_alpha(self, alpha): + self.color_alpha = (alpha*0.01) + color_list = list(self.new_color) + color_list[-1] = self.color_alpha + self.new_color = tuple(color_list) + + def update_grid_alpha(self, alpha): + self.grid_alpha_value = (alpha*0.01) + + def background_color(self, color): + self.bg_color = color = color + + def update_fov(self, num): + self.fov = num + self.camera_zoom = self.camera_distance(num) + self.update() + + def camera_distance(self, num): + return 1 / (math.tan(math.radians(num / 2))) + + def update_grid_cell(self, cells): + self.cell = cells + self.grid = grid(self.size, self.cell) + self.update_grid() + + def update_grid_size(self, size): + self.size = size + self.grid = grid(self.size, self.cell) + self.update_grid() + + def update_grid(self): + self.vbo = self.ctx.buffer(self.grid.astype('f4')) + self.vao2 = self.ctx.simple_vertex_array(self.prog, self.vbo, 'in_position') + + def resizeGL(self, width, height): + width = max(2, width) + height = max(2, height) + self.ctx.viewport = (0, 0, width, height) + self.arc_ball.setBounds(width, height) + return + + def make_wireframe(self): + self.is_wireframe = True + + def make_solid(self): + self.is_wireframe = False + + # Input handling + def mousePressEvent(self, event): + if event.buttons() & QtCore.Qt.LeftButton: + self.arc_ball.onClickLeftDown(event.x(), event.y()) + elif event.buttons() & QtCore.Qt.RightButton: + self.prev_x = event.x() + self.prev_y = event.y() + + def mouseReleaseEvent(self, event): + if event.buttons() & QtCore.Qt.LeftButton: + self.arc_ball.onClickLeftUp() + + def mouseMoveEvent(self, event): + if event.buttons() & QtCore.Qt.LeftButton: + self.arc_ball.onDrag(event.x(), event.y()) + + def update_zoom(self, event): + self.camera_zoom += event.angleDelta().y() * 0.001 + if self.camera_zoom < 0.1: + self.camera_zoom = 0.1 + self.update() + + def mouseMoveEvent(self, event): + if event.buttons() & QtCore.Qt.LeftButton: + self.arc_ball.onDrag(event.x(), event.y()) + elif event.buttons() & QtCore.Qt.RightButton: + x_movement = event.x() - self.prev_x + y_movement = event.y() - self.prev_y + self.center[0] -= x_movement * 0.01 + self.center[1] += y_movement * 0.01 + self.update() + self.prev_x = event.x() + self.prev_y = event.y()
\ No newline at end of file diff --git a/functions.py b/functions.py new file mode 100644 index 0000000..043bc16 --- /dev/null +++ b/functions.py @@ -0,0 +1,155 @@ +from PyQt5.QtWidgets import QColorDialog, QMessageBox +from PyQt5 import QtWidgets +from OpenGL.GLUT import * +import openmesh +import re + + +def open_file( opengl_obj, obj_path, obj_name, uv_label, material_label, drawcalls_label, vertices_label, triangles_label, edges_label): + file_name = QtWidgets.QFileDialog.getOpenFileName( + None, 'Open file', '', "Mesh files (*.obj *.stl *.ply *.off *.om)") + if not file_name[0]: + return + mesh = openmesh.read_trimesh(file_name[0]) + opengl_obj.set_mesh(mesh) + set_name(file_name, obj_path, obj_name) + set_file_info(mesh, vertices_label, triangles_label, edges_label) + + _, file_extension = os.path.splitext(file_name[0]) + file_format = file_extension.replace(".", "") + if file_format == "obj": + has_uv(file_name[0], uv_label) + materials(file_name[0], material_label) + draw_calls(file_name[0], drawcalls_label) + + +def set_name(file_name, obj_path, obj_name): + file_path = os.path.normpath(file_name[0]) + ob_name = os.path.basename(file_name[0]) + obj_path.setText(file_path) + obj_name.setText(ob_name) + + +def set_file_info(mesh, vertices_label, triangles_label, edges_label): + vertex_count = mesh.n_vertices() + triangle_count = mesh.n_faces() + edges_count = mesh.n_edges() + vertices_label.setText(str(vertex_count)) + triangles_label.setText(str(triangle_count)) + edges_label.setText(str(edges_count)) + + +def has_uv(file_path, has_label): + with open(file_path, "r") as file: + contents = file.read() + if "vt" in contents: + has_label.setText(str("Yes")) + else: + has_label.setText(str("No")) + + +def materials(file_path, material_label): + with open(file_path, "r") as file: + contents = file.read() + num = set(re.findall(r'usemtl (\S+)', contents)) + material_label.setText(str(len(num))) + + +def draw_calls(file_path, drawcalls_label): + with open(file_path, "r") as file: + contents = file.read() + draw = tuple(re.findall(r'usemtl (\S+)', contents)) + if len(draw)>1: + drawcalls_label.setText(str(len(draw))) + else: + drawcalls_label.setText(str(1)) + + +def get_color(button, button_color, btn_name, openGL): + color_dialog = QColorDialog() + color = color_dialog.getColor() + if color.isValid(): + r, g, b, a = color.getRgb() + color = f"rgb({r}, {g}, {b})" + button_color(button, color) + if btn_name == "background": + openGL.background_color((r / 255, g / 255, b / 255)) + if btn_name == "wire": + openGL.change_light_color((r/255, g/255, b/255)) + + +def set_button_color(button, color): + button.setStyleSheet(f"background-color: {color};" + f"border-radius: 2px" + ) + + +def change_slider(slider, line, openGL, btn_name=""): + value = slider.value() + line.setText(str(value)) + if btn_name == "fov": + value = slider.value() + openGL.update_fov(value) + + if btn_name == "wireframe": + value = slider.value() + openGL.update_alpha(value) + + if btn_name == "grid": + value = slider.value() + openGL.update_grid_alpha(value) + + +def updateSlider(slider, line): + value = int(line.text()) + slider.setValue(value) + + +def update_grid_size(text, openGL, btn_name): + value = int(text.text()) + if btn_name == "cell": + openGL.update_grid_cell(value) + if btn_name == "size": + openGL.update_grid_size(value) + + +def close_file(openGL, obj_path, obj_name): + openGL.set_mesh(None) + obj_path.setText("") + obj_name.setText("") + + +def show_message_box(): + title = "About Qt 3DViewer" + message = "Qt 3DViewer is a compact tool for \n" \ + "viewing 3D models in a user friendly way\n" \ + "Designed and Developed by Alon Rubin.\n\n" \ + "Powered by: Python 3.9, Qt Designer,\n " \ + "PyQt5, OpenGL, OpenMesh and ModernGL.\n\n" \ + "Movement:\n" \ + "• Left mouse button to rotate\n" \ + "• Mouse wheel to zoom\n" \ + "• Right mouse button to pan." + msg = QMessageBox() + msg.setStyleSheet(""" + QMessageBox { + background-color: rgb(56, 56, 56); + letter-spacing: 0.4cm; + font-size: 14px; + color: rgb(145, 145, 145); + } + width: 60px; + color: rgb(200, 200, 200); + background-color: rgb(56, 56, 56); + padding: 10px; + width: 60px; + """ + ) + msg.setWindowTitle(title) + msg.setText(message) + msg.setStandardButtons(QMessageBox.Close) + msg.exec_() + + +def exit_app(): + sys.exit()
\ No newline at end of file @@ -0,0 +1,67 @@ +from PyQt5 import QtWidgets, QtCore, uic +from PyQt5.QtGui import QIcon +from OpenGL.GLUT import * +from engine import QGLControllerWidget +import functions as f + + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self): + # Load UI file + QtWidgets.QMainWindow.__init__(self) + uic.loadUi("resource/3DView02.ui", self) + + # Create openGL context + self.openGL = QGLControllerWidget(self) + self.openGL.setGeometry(0, 37, 870, 731) + timer = QtCore.QTimer(self) + timer.setInterval(20) # refresh speed in milliseconds + timer.timeout.connect(self.openGL.updateGL) + timer.start() + + # Load button + load_icon = QIcon("resource/load.png") + self.load_button.setIcon(load_icon) + + def load_file(): + f.open_file(self.openGL, self.obj_path_label, self.obj_name_label, self.uv2_label, self.material_label, + self.drawcalls_label, self.vertices_label, self.triangles_label, self.edges_label) + + self.load_button.clicked.connect(load_file) + self.actionLoad.triggered.connect(load_file) + + # Menubar Buttons + self.actionQuit.triggered.connect(lambda: f.exit_app()) + self.actionClose.triggered.connect(lambda: f.close_file(self.openGL, self.obj_path_label, self.obj_name_label)) + self.actionAbout.triggered.connect(lambda: f.show_message_box()) + + # Buttons + self.wireframe_color.clicked.connect(lambda: f.get_color(self.wireframe_color, f.set_button_color, "wire", self.openGL)) + self.background_color.clicked.connect(lambda: f.get_color(self.background_color, f.set_button_color, "background", self.openGL)) + + # Settings Sliders + self.fov_slider.valueChanged.connect(lambda: f.change_slider(self.fov_slider, self.fov_slider_value, self.openGL, "fov")) + self.fov_slider_value.textChanged.connect(lambda: f.updateSlider(self.fov_slider, self.fov_slider_value)) + self.grid_slider.valueChanged.connect(lambda: f.change_slider(self.grid_slider, self.grid_slider_value, self.openGL, "na")) + self.grid_slider_value.textChanged.connect(lambda: f.updateSlider(self.grid_slider, self.grid_slider_value)) + + # Settings Sliders + self.wireframe_slider.valueChanged.connect(lambda: f.change_slider(self.wireframe_slider, self.wireframe_slider_value, self.openGL, "wireframe")) + self.wireframe_slider_value.textChanged.connect(lambda: f.updateSlider(self.wireframe_slider, self.wireframe_slider_value)) + + # Settings radio buttons + self.wireframe_radio.toggled.connect(lambda: self.openGL.make_wireframe()) + self.solid_radio.toggled.connect(lambda: self.openGL.make_solid()) + + # Grid settings + self.grid_cell.textChanged.connect(lambda: f.update_grid_size(self.grid_cell, self.openGL, "cell")) + self.grid_size.textChanged.connect(lambda: f.update_grid_size(self.grid_size, self.openGL, "size")) + self.grid_slider.valueChanged.connect(lambda: f.change_slider(self.grid_slider, self.grid_slider_value, self.openGL, "grid")) + self.grid_slider_value.textChanged.connect(lambda: f.updateSlider(self.grid_slider, self.grid_slider_value)) + + +if __name__ == '__main__': + app = QtWidgets.QApplication(sys.argv) + win = MainWindow() + win.show() + sys.exit(app.exec_())
\ No newline at end of file diff --git a/resource/3DView02.ui b/resource/3DView02.ui new file mode 100644 index 0000000..68658a6 --- /dev/null +++ b/resource/3DView02.ui @@ -0,0 +1,1612 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1150</width> + <height>800</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>1150</width> + <height>800</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>1150</width> + <height>800</height> + </size> + </property> + <property name="windowTitle"> + <string>Qt 3DViewer</string> + </property> + <widget class="QWidget" name="centralwidget"> + <widget class="QFrame" name="frame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1150</width> + <height>800</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>1150</width> + <height>800</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QOpenGLWidget" name="openGLWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>870</width> + <height>731</height> + </rect> + </property> + </widget> + <widget class="QFrame" name="frame_2"> + <property name="geometry"> + <rect> + <x>871</x> + <y>0</y> + <width>275</width> + <height>50</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(45, 45, 45);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="obj_name_label"> + <property name="geometry"> + <rect> + <x>50</x> + <y>10</y> + <width>211</width> + <height>31</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(210, 210, 210);</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QPushButton" name="load_button"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>30</width> + <height>30</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>6</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { +background-color: rgb(56, 56, 56); +border-radius: 2px +} + +QPushButton:hover { +background-color: rgb(65, 65, 65); +border-radius: 2px +} + +QPushButton:pressed { + background-color: rgb(50,50,50); +}</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </widget> + <widget class="QTabWidget" name="tabWidget_2"> + <property name="geometry"> + <rect> + <x>870</x> + <y>50</y> + <width>279</width> + <height>681</height> + </rect> + </property> + <property name="baseSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>8</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QTabWidget::pane { + border: 1px solid lightgray; + border-color: rgb(38, 38, 38); + top:-1px; + background: rgb(245, 245, 245); +} + +QTabBar::tab { + background: rgb(45, 45, 45); + color: rgb(128, 128, 128); + border: 1px solid lightgray; + border-color: rgb(38, 38, 38); + padding: 8px; + padding-left:49px; + padding-right: 49px; +} +QTabBar::tab:hover { + background: rgb(51, 51, 51); +} +QTabBar::tab:selected { + background: rgb(56, 56, 56); + color: rgb(210, 210, 210); +} + +QTabWidget QStackedWidget > QWidget { + background-color: rgb(56, 56, 56); +} +QTabBar { + font: 10pt "Microsoft YaHei UI"; + }</string> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tab_1"> + <attribute name="title"> + <string>Data</string> + </attribute> + <widget class="QLabel" name="mesh_label"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>71</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Mesh</string> + </property> + </widget> + <widget class="QLabel" name="mesh_label_2"> + <property name="geometry"> + <rect> + <x>40</x> + <y>40</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Triangles</string> + </property> + </widget> + <widget class="QLabel" name="triangles_label"> + <property name="geometry"> + <rect> + <x>150</x> + <y>40</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="vertices_label"> + <property name="geometry"> + <rect> + <x>150</x> + <y>70</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="mesh_label_5"> + <property name="geometry"> + <rect> + <x>40</x> + <y>70</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Vertices</string> + </property> + </widget> + <widget class="QLabel" name="edges_label"> + <property name="geometry"> + <rect> + <x>150</x> + <y>100</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="mesh_label_7"> + <property name="geometry"> + <rect> + <x>40</x> + <y>130</y> + <width>101</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>UV coordinates</string> + </property> + </widget> + <widget class="QLabel" name="uv2_label"> + <property name="geometry"> + <rect> + <x>150</x> + <y>130</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>No</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="edges_label_test"> + <property name="geometry"> + <rect> + <x>40</x> + <y>100</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Edges</string> + </property> + </widget> + <widget class="QLabel" name="drawcalls_label"> + <property name="geometry"> + <rect> + <x>150</x> + <y>190</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>1</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="mesh_label_11"> + <property name="geometry"> + <rect> + <x>40</x> + <y>160</y> + <width>101</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Material IDS</string> + </property> + </widget> + <widget class="QLabel" name="material_label"> + <property name="geometry"> + <rect> + <x>150</x> + <y>160</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="mesh_label_13"> + <property name="geometry"> + <rect> + <x>40</x> + <y>190</y> + <width>101</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Draw Calls</string> + </property> + </widget> + <widget class="QFrame" name="frame_3"> + <property name="geometry"> + <rect> + <x>0</x> + <y>230</y> + <width>280</width> + <height>1</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QFrame" name="frame_4"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>280</width> + <height>1</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QFrame" name="frame_10"> + <property name="geometry"> + <rect> + <x>0</x> + <y>480</y> + <width>280</width> + <height>201</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QLabel" name="mesh_label_18"> + <property name="geometry"> + <rect> + <x>70</x> + <y>290</y> + <width>91</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Solid</string> + </property> + </widget> + <widget class="QRadioButton" name="solid_radio"> + <property name="geometry"> + <rect> + <x>40</x> + <y>290</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">QRadioButton::indicator { + width: 20px; + height: 20px; + border-radius: 2px +} +QRadioButton::indicator::unchecked { + background-color: rgb(45, 45, 45); +} +QRadioButton::indicator:unchecked:hover { + background-color: rgb(50, 50, 50); +} +QRadioButton::indicator::checked { + background-color: rgb(30, 150, 220); +}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="mesh_label_30"> + <property name="geometry"> + <rect> + <x>50</x> + <y>433</y> + <width>51</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Opacity</string> + </property> + </widget> + <widget class="QLabel" name="mesh_label_24"> + <property name="geometry"> + <rect> + <x>160</x> + <y>290</y> + <width>91</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Wireframe</string> + </property> + </widget> + <widget class="QRadioButton" name="wireframe_radio"> + <property name="geometry"> + <rect> + <x>130</x> + <y>290</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">QRadioButton::indicator { + width: 20px; + height: 20px; + border-radius: 2px +} +QRadioButton::indicator::unchecked { + background-color: rgb(45, 45, 45); +} +QRadioButton::indicator:unchecked:hover { + background-color: rgb(50, 50, 50); +} +QRadioButton::indicator::checked { + background-color: rgb(30, 150, 220); +}</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QLabel" name="mesh_label_10"> + <property name="geometry"> + <rect> + <x>20</x> + <y>250</y> + <width>71</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>View</string> + </property> + </widget> + <widget class="QFrame" name="frame_11"> + <property name="geometry"> + <rect> + <x>40</x> + <y>390</y> + <width>151</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(45, 45, 45);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="mesh_label_19"> + <property name="geometry"> + <rect> + <x>10</x> + <y>0</y> + <width>71</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Color</string> + </property> + </widget> + </widget> + <widget class="QToolButton" name="wireframe_color"> + <property name="geometry"> + <rect> + <x>210</x> + <y>390</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true"> QToolButton{ + background-color: rgb(160, 160, 160); + color: rgb(145, 145, 145); + border-radius: 2px +} +QToolButton:hover { +background:rgba(160, 160, 160,.8); +}</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QSlider" name="wireframe_slider"> + <property name="geometry"> + <rect> + <x>40</x> + <y>430</y> + <width>151</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">QSlider { + background-color: rgb(45, 45, 45); +} + +QSlider::groove:horizontal { +background: rgb(45, 45, 45); +} + +QSlider::handle:horizontal { + background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f); + width: 10px; + background: rgb(30, 150, 220); +}</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + <widget class="QLineEdit" name="wireframe_slider_value"> + <property name="geometry"> + <rect> + <x>210</x> + <y>430</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QLineEdit { + border: 2px solid gray; + color: rgb(145, 145, 145); + border-color: rgb(45, 45, 45); + background-color: rgb(45, 45, 45); +}</string> + </property> + <property name="text"> + <string>100</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="mesh_label_15"> + <property name="geometry"> + <rect> + <x>20</x> + <y>350</y> + <width>71</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Model</string> + </property> + </widget> + <zorder>mesh_label</zorder> + <zorder>mesh_label_2</zorder> + <zorder>triangles_label</zorder> + <zorder>vertices_label</zorder> + <zorder>mesh_label_5</zorder> + <zorder>edges_label</zorder> + <zorder>mesh_label_7</zorder> + <zorder>uv2_label</zorder> + <zorder>edges_label_test</zorder> + <zorder>drawcalls_label</zorder> + <zorder>mesh_label_11</zorder> + <zorder>material_label</zorder> + <zorder>mesh_label_13</zorder> + <zorder>frame_3</zorder> + <zorder>frame_4</zorder> + <zorder>frame_10</zorder> + <zorder>mesh_label_18</zorder> + <zorder>solid_radio</zorder> + <zorder>mesh_label_24</zorder> + <zorder>wireframe_radio</zorder> + <zorder>mesh_label_10</zorder> + <zorder>frame_11</zorder> + <zorder>wireframe_color</zorder> + <zorder>wireframe_slider</zorder> + <zorder>wireframe_slider_value</zorder> + <zorder>mesh_label_15</zorder> + <zorder>mesh_label_30</zorder> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Settings</string> + </attribute> + <widget class="QLabel" name="mesh_label_14"> + <property name="geometry"> + <rect> + <x>40</x> + <y>245</y> + <width>51</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent; +selectByMouse: false</string> + </property> + <property name="text"> + <string>Opacity</string> + </property> + </widget> + <widget class="QFrame" name="frame_8"> + <property name="geometry"> + <rect> + <x>20</x> + <y>280</y> + <width>170</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(45, 45, 45);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="mesh_label_12"> + <property name="geometry"> + <rect> + <x>20</x> + <y>0</y> + <width>91</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Cells amount</string> + </property> + </widget> + </widget> + <widget class="QToolButton" name="background_color"> + <property name="geometry"> + <rect> + <x>200</x> + <y>40</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true"> QToolButton{ + background-color: rgb(200, 200, 200); + color: rgb(145, 145, 145); + border-radius: 2px +} +QToolButton:hover { + background-color: rgb(220, 220, 220); +}</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QFrame" name="frame_6"> + <property name="geometry"> + <rect> + <x>0</x> + <y>90</y> + <width>280</width> + <height>1</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QSlider" name="grid_slider"> + <property name="geometry"> + <rect> + <x>20</x> + <y>240</y> + <width>170</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">QSlider { + background-color: rgb(45, 45, 45); +} + +QSlider::groove:horizontal { +background: rgb(45, 45, 45); +} + +QSlider::handle:horizontal { + background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f); + width: 10px; + background: rgb(30, 150, 220); +}</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + <widget class="QSlider" name="fov_slider"> + <property name="geometry"> + <rect> + <x>20</x> + <y>140</y> + <width>170</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">QSlider { + background-color: rgb(45, 45, 45); +} + +QSlider::groove:horizontal { +background: rgb(45, 45, 45); +} + +QSlider::handle:horizontal { + background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f); + width: 10px; + background: rgb(30, 150, 220); +}</string> + </property> + <property name="minimum"> + <number>10</number> + </property> + <property name="maximum"> + <number>120</number> + </property> + <property name="sliderPosition"> + <number>60</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + <widget class="QLineEdit" name="fov_slider_value"> + <property name="geometry"> + <rect> + <x>200</x> + <y>140</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QLineEdit { + border: 2px solid gray; + color: rgb(145, 145, 145); + border-color: rgb(45, 45, 45); + background-color: rgb(45, 45, 45); +}</string> + </property> + <property name="text"> + <string>60</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QFrame" name="frame_7"> + <property name="geometry"> + <rect> + <x>0</x> + <y>190</y> + <width>280</width> + <height>1</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QLineEdit" name="grid_slider_value"> + <property name="geometry"> + <rect> + <x>200</x> + <y>240</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QLineEdit { + border: 2px solid gray; + color: rgb(145, 145, 145); + border-color: rgb(45, 45, 45); + background-color: rgb(45, 45, 45); +}</string> + </property> + <property name="text"> + <string>100</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="mesh_label_3"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>91</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Background</string> + </property> + </widget> + <widget class="QLabel" name="mesh_label_8"> + <property name="geometry"> + <rect> + <x>20</x> + <y>210</y> + <width>91</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Grid</string> + </property> + </widget> + <widget class="QLabel" name="mesh_label_6"> + <property name="geometry"> + <rect> + <x>20</x> + <y>110</y> + <width>91</width> + <height>16</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(175, 175, 175); +background: transparent;</string> + </property> + <property name="text"> + <string>Field of view</string> + </property> + </widget> + <widget class="QFrame" name="frame_5"> + <property name="geometry"> + <rect> + <x>20</x> + <y>40</y> + <width>170</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(45, 45, 45);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="mesh_label_4"> + <property name="geometry"> + <rect> + <x>20</x> + <y>0</y> + <width>71</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Color</string> + </property> + </widget> + </widget> + <widget class="QFrame" name="frame_9"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>280</width> + <height>311</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(38, 38, 38);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QLineEdit" name="grid_cell"> + <property name="geometry"> + <rect> + <x>200</x> + <y>280</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QLineEdit { + border: 2px solid gray; + color: rgb(145, 145, 145); + border-color: rgb(45, 45, 45); + background-color: rgb(45, 45, 45); +}</string> + </property> + <property name="text"> + <string>50</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLineEdit" name="grid_size"> + <property name="geometry"> + <rect> + <x>200</x> + <y>320</y> + <width>60</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QLineEdit { + border: 2px solid gray; + color: rgb(145, 145, 145); + border-color: rgb(45, 45, 45); + background-color: rgb(45, 45, 45); +}</string> + </property> + <property name="text"> + <string>20</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QFrame" name="frame_12"> + <property name="geometry"> + <rect> + <x>20</x> + <y>320</y> + <width>170</width> + <height>25</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(45, 45, 45);</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="mesh_label_16"> + <property name="geometry"> + <rect> + <x>20</x> + <y>0</y> + <width>71</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>10</pointsize> + <weight>50</weight> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string>Size</string> + </property> + </widget> + </widget> + <zorder>frame_8</zorder> + <zorder>background_color</zorder> + <zorder>frame_6</zorder> + <zorder>grid_slider</zorder> + <zorder>fov_slider</zorder> + <zorder>fov_slider_value</zorder> + <zorder>frame_7</zorder> + <zorder>grid_slider_value</zorder> + <zorder>mesh_label_3</zorder> + <zorder>mesh_label_8</zorder> + <zorder>mesh_label_6</zorder> + <zorder>frame_5</zorder> + <zorder>frame_9</zorder> + <zorder>grid_cell</zorder> + <zorder>mesh_label_14</zorder> + <zorder>grid_size</zorder> + <zorder>frame_12</zorder> + </widget> + </widget> + <widget class="QLabel" name="obj_path_label"> + <property name="geometry"> + <rect> + <x>14</x> + <y>731</y> + <width>1131</width> + <height>31</height> + </rect> + </property> + <property name="font"> + <font> + <family>Microsoft YaHei UI</family> + <pointsize>9</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(145, 145, 145); +background: transparent;</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </widget> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1150</width> + <height>37</height> + </rect> + </property> + <property name="statusTip"> + <string/> + </property> + <property name="styleSheet"> + <string notr="true">QMenuBar { +background: rgb(38, 38, 38); + padding: 8px; + color: rgb(210, 210, 210); +} + +QMenuBar::item { + background: transparent; +} + +QMenuBar::item:selected { + background: rgb(56, 56, 56); + padding: 20px; + spacing: 20px; +} + +QMenuBar::item:pressed { + background: rgb(56, 56, 56); + padding: 20px; + spacing: 20px; +} + +QMenu { + background: rgb(38, 38, 38); + padding: 10px; + color: rgb(210, 210, 210); + +} + +QMenu::item { + background-color: transparent; + padding: 5px; +padding-left: 10px; +padding-right: 150px; +} + +QMenu::item:selected { + background: rgb(56, 56, 56); + spacing: 20px; +}</string> + </property> + <widget class="QMenu" name="menuFile"> + <property name="title"> + <string>File</string> + </property> + <addaction name="actionLoad"/> + <addaction name="actionClose"/> + <addaction name="separator"/> + <addaction name="actionQuit"/> + </widget> + <widget class="QMenu" name="menuAbout"> + <property name="title"> + <string>About</string> + </property> + <addaction name="actionAbout"/> + </widget> + <addaction name="menuFile"/> + <addaction name="menuAbout"/> + </widget> + <action name="actionLoad"> + <property name="text"> + <string>Load</string> + </property> + </action> + <action name="actionClose"> + <property name="text"> + <string>Close</string> + </property> + </action> + <action name="actionQuit"> + <property name="text"> + <string>Quit</string> + </property> + </action> + <action name="actionAbout"> + <property name="text"> + <string>About</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> diff --git a/resource/app_preview.PNG b/resource/app_preview.PNG Binary files differnew file mode 100644 index 0000000..d26f68c --- /dev/null +++ b/resource/app_preview.PNG diff --git a/resource/load.png b/resource/load.png Binary files differnew file mode 100644 index 0000000..2c5a34c --- /dev/null +++ b/resource/load.png diff --git a/resource/shaders.py b/resource/shaders.py new file mode 100644 index 0000000..7fce7ca --- /dev/null +++ b/resource/shaders.py @@ -0,0 +1,47 @@ +vertex_shader=''' + #version 330 + + uniform mat4 Mvp; + + in vec3 in_position; + in vec3 in_normal; + in vec2 in_texcoord_0; + + out vec3 v_vert; + out vec3 v_norm; + out vec2 v_text; + + void main() { + v_vert = in_position; + v_norm = in_normal; + v_text = in_texcoord_0; + gl_Position = Mvp * vec4(in_position, 1.0); + } + ''' +fragment_shader=''' + #version 330 + + uniform sampler2D Texture; + uniform vec4 Color; + uniform vec3 Light; + + in vec3 v_vert; + in vec3 v_norm; + in vec2 v_text; + + out vec4 f_color; + + void main() { + float lum = -dot(normalize(v_norm), normalize(v_vert + Light)); + lum = acos(lum) / 3.14159265; + lum = clamp(lum, 0.0, 1.0); + lum = lum * lum; + lum = smoothstep(0.0, 1.0, lum); + lum *= smoothstep(0.0, 80.0, v_vert.z) * 0.3 + 0.7; + lum = lum * 0.8 + 0.2; + + vec3 color = texture(Texture, v_text).rgb; + color = color * (1.0 - Color.a) + Color.rgb * Color.a; + f_color = vec4(color * lum, Color.a); + } + ''' |
