Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 158 additions & 2 deletions xml_editor/view/opengl_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

from PyQt5.QtWidgets import QOpenGLWidget, QSizePolicy
from PyQt5.QtCore import Qt, QSize, QPoint, pyqtSignal
from PyQt5.QtCore import Qt, QSize, QPoint, pyqtSignal, QTimer
from PyQt5.QtGui import QMouseEvent, QWheelEvent, QKeyEvent

import numpy as np
Expand All @@ -28,6 +28,14 @@
print(f"警告: 无法初始化GLUT: {e}")
raise e

# yc
# 添加 DISCOVERSE 项目的根目录到 sys.path
sys.path.append(os.path.abspath('/root/DISCOVERSE'))
# 导入 GSRenderer
from discoverse.gaussian_renderer.gsRenderer import GSRenderer
# import cv2 as cv
# import os

class OpenGLView(QOpenGLWidget):
"""
OpenGL视图类
Expand Down Expand Up @@ -66,6 +74,10 @@ def __init__(self, scene_viewmodel: SceneViewModel, parent=None):
self._camera_rotation_x = 30.0 # 俯仰角
self._camera_rotation_y = -45.0 # 偏航角
self._camera_target = np.array([0.0, 0.0, 0.0])
# self._camera_distance = 9.0
# self._camera_rotation_x = 10.0 # 俯仰角
# self._camera_rotation_y = -24.0 # 偏航角
# self._camera_target = np.array([2.12316528 ,4.76870729 ,-0.36])

# 连接信号
self._scene_viewmodel.geometriesChanged.connect(self.update)
Expand Down Expand Up @@ -99,6 +111,23 @@ def __init__(self, scene_viewmodel: SceneViewModel, parent=None):
# 拖拽预览数据
self.drag_preview = {'active': False, 'position': None, 'type': None}

# yc 初始化gaussian renderer, 设置高斯背景ply
self.model_dict = {"background":"lobby2kfc.ply"}
self.gs_renderer = GSRenderer(self.model_dict, self.width(), self.height())
self.index = 0

# # 为了动画效果
# self.animation_dir = "/home/yuchi/renders"
# self.mask_dir = "/home/yuchi/renders_mask"
# self.target_fps = 30
# self.num_frames = 150
# self.frame_index = 0
# self.animation = False
# self.animation_imgs = []
# self.masks = []
# self._timer = QTimer(self)
# self._timer.timeout.connect(self._on_click)

def minimumSizeHint(self):
"""返回建议的最小尺寸"""
return QSize(200, 150)
Expand Down Expand Up @@ -128,8 +157,62 @@ def initializeGL(self):
def resizeGL(self, width, height):
"""处理窗口大小变化事件"""
glViewport(0, 0, width, height)
# yc 高斯渲染的分辨率跟GL保持一致
self.gs_renderer.set_camera_resolution(height,width)
self._update_projection(width, height)


# yc 得到高斯渲染结果 numpy数组
def get_gs_result(self):
self.gs_renderer.renderer.update_camera_pose(self.gs_renderer.camera)
return self.gs_renderer.render()

def initialize_gs_texture(self, width, height):
"""初始化 gs 纹理(或重新分配尺寸)"""
if not hasattr(self, "gs_texture"):
# 第一次创建
self.gs_texture = glGenTextures(1)

glBindTexture(GL_TEXTURE_2D, self.gs_texture)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1) # 关键:解决 RGB 对齐问题
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
# 分配新的纹理内存(RGB, uint8)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, None)
glBindTexture(GL_TEXTURE_2D, 0)

# 记录当前纹理尺寸
self.gs_tex_width = width
self.gs_tex_height = height

# def start_animation(self):
# """点击按钮后调用:预加载图片并以30FPS播放150帧"""
# self.animation_imgs.clear()
# self.masks.clear()
# for i in range(self.num_frames):
# image = cv.imread(os.path.join(self.animation_dir, f"frame_{int(i):06d}.png"))
# image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
# mask = cv.imread(os.path.join(self.mask_dir, f"frame_{int(i):06d}_mask.png"))
# self.animation_imgs.append(image)
# self.masks.append(mask)
# self.animation = True
# self.frame_index = 0
# self._timer.start(round(1000 / self.target_fps))
# self.update()

# def _on_click(self):
# """定时器回调:只负责触发重绘和收尾"""
# if not self.animation:
# self._timer.stop()
# return
# if self.frame_index >= self.num_frames:
# self.animation = False
# self._timer.stop()
# # self.finished.emit()
# return
# self.update()

def paintGL(self):
"""渲染场景"""
# 清除缓冲区
Expand Down Expand Up @@ -175,11 +258,74 @@ def paintGL(self):
glDisable(GL_DEPTH_TEST)
self._draw_drag_preview()
glEnable(GL_DEPTH_TEST)

# ---- 2. 获取高斯渲染结果 ----
gs_result = self.get_gs_result()
# cv.imwrite(f'./test.png', gs_result)
# if self.animation:
# img = self.animation_imgs[self.frame_index]
# mask = self.masks[self.frame_index]
# self.frame_index += 1
# gs_result = np.where(mask.astype(bool), gs_result, img)
# if self.frame_index > self.num_frames-1:
# self.animation = False
# 垂直翻转,需要的话(openGL以左下角为原点)
gs_result = np.flipud(gs_result)


height,width,_ = gs_result.shape
print("gs shape",gs_result.shape)

# ---- 3. 初始化/检查纹理尺寸 ----
if (not hasattr(self, "gs_texture") or
width != getattr(self, "gs_tex_width", None) or
height != getattr(self, "gs_tex_height", None)):
self.initialize_gs_texture(width, height)

# ---- 4. 更新纹理内容 ----
glBindTexture(GL_TEXTURE_2D, self.gs_texture)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1) # 确保对齐
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
GL_RGB, GL_UNSIGNED_BYTE, gs_result)

# ---- 5. 绘制全屏 Quad ----
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
glOrtho(0, 1, 0, 1, -1, 1)

glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()

glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, self.gs_texture)
glColor4f(1, 1, 1, 0.6) # 半透明叠加

glBegin(GL_QUADS)
glTexCoord2f(0, 0); glVertex2f(0, 0)
glTexCoord2f(1, 0); glVertex2f(1, 0)
glTexCoord2f(1, 1); glVertex2f(1, 1)
glTexCoord2f(0, 1); glVertex2f(0, 1)
glEnd()

glDisable(GL_TEXTURE_2D)
glDisable(GL_BLEND)

glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()

glBindTexture(GL_TEXTURE_2D, 0)

def _update_projection(self, width, height):
"""更新投影矩阵"""
aspect = width / height if height > 0 else 1.0
gluPerspective(45.0, aspect, 0.1, 100.0)
gluPerspective(60.17, aspect, 0.1, 100.0)

def _update_camera_config(self):
"""更新摄像机配置到场景视图模型(基于Z轴向上的坐标系)"""
Expand Down Expand Up @@ -209,6 +355,16 @@ def _update_camera_config(self):
'projection_matrix': projection_matrix,
'view_matrix': modelview_matrix
})

# yc
# 更新高斯渲染的相机视角
self.gs_renderer.camera.position = camera_position
self.gs_renderer.camera.target = self._camera_target
print("camera_position", camera_position)
print('target position',self._camera_target)
print('camera distance',self._camera_distance)
print('camera rotation x',self._camera_rotation_x) # 俯仰角
print('camera_rotation_y',self._camera_rotation_y) # 偏航角

def _draw_grid(self):
"""绘制地面网格"""
Expand Down