# -*- coding: utf-8-*- """ Module : Panda3DWorld Author : Saifeddine ALOUI Description : Inherit this object to create your custom world """ import sys import os from core.CustomMouseController import CustomMouseController # 获取 RenderPipelineFile 的路径 render_pipeline_path = './RenderPipelineFile' # 将该路径添加到 sys.path 中,确保 Python 能够找到它 project_root = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, project_root) sys.path.insert(0, render_pipeline_path) # 现在你可以导入 RenderPipelineFile 中的模块了 # 例如,如果你想导入 RenderPipelineFile 中的 RenderPipeline 模块 from RenderPipelineFile.rpcore import RenderPipeline _global_render_pipeline = None # PyQt imports from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * # Panda imports from panda3d.core import * # from panda3d.core import loadPrcFileData # loadPrcFileData("", "window-type none") # Set Panda to draw its main window in an offscreen buffer from direct.showbase.DirectObject import DirectObject from panda3d.core import GraphicsOutput, Texture, ConfigVariableManager, WindowProperties # Set up Panda environment from direct.showbase.ShowBase import ShowBase import platform # Local imports from QPanda3D.QMouseWatcherNode import QMouseWatcherNode from RenderPipelineFile.rpcore.render_target import RenderTarget __all__ = ["Panda3DWorld"] _global_world_instance=None import builtins class Panda3DWorld(ShowBase): """ Panda3DWorld : A class to handle all panda3D world manipulation """ def __init__(self, width=1380, height=750, is_fullscreen=False, size=1.0, clear_color=LVecBase4f(0, 0.5, 0, 1), name="qpanda3D"): global _global_world_instance global _global_render_pipeline _global_world_instance = self sort = -100 self.parent = None # 设置基本配置 loadPrcFileData("", "show-frame-rate-meter 0") loadPrcFileData("", "window-type offscreen") # 设置为离屏渲染 loadPrcFileData("", f"win-size {width} {height}") loadPrcFileData("", "win-fixed-size #f") # 允许窗口调整大小 # 🚀 VR性能优化配置 loadPrcFileData("", "prefer-single-buffer true") # 减少缓冲区交换开销 loadPrcFileData("", "gl-force-flush false") # 避免强制glFlush导致的性能损失 loadPrcFileData("", "sync-video false") # 禁用默认VSync,让OpenVR控制 loadPrcFileData("", "support-stencil false") # 禁用不必要的模板缓冲区 loadPrcFileData("", "clock-mode non-real-time") # 禁用Panda3D帧率控制,让OpenVR控制 # loadPrcFileData("", "gl-debug true") # 调试时可启用OpenGL调试 if (is_fullscreen): loadPrcFileData("", "fullscreen #t") self.render_pipeline = RenderPipeline() self.render_pipeline.pre_showbase_init() ShowBase.__init__(self) # 初始化渲染管线并设置可调整大小的标志 self.render_pipeline.create(self) _global_render_pipeline = self.render_pipeline # 创建 Qt 能读的 RGBA8 贴图 self.qt_output_tex = Texture("qt_output_tex") self.qt_output_tex.set_format(Texture.F_rgba8) self.qt_output_tex.set_component_type(Texture.T_unsigned_byte) # # 获取图形管线对象 # gsg = self.win.getGsg() # host = gsg.getEngine().getHost() self.win.add_render_texture(self.qt_output_tex, GraphicsOutput.RTM_copy_ram) #self.screenTexture = Texture() #self.screenTexture.setMinfilter(Texture.FTLinear) #self.screenTexture.setFormat(Texture.FRgba32) #self.screenTexture.set_wrap_u(Texture.WM_clamp) #self.screenTexture.set_wrap_v(Texture.WM_clamp) # buff_size_x = int(self.win.get_x_size() * size) # buff_size_y = int(self.win.get_y_size() * size) # winprops = WindowProperties() # winprops.set_size(buff_size_x, buff_size_y) # # # props = FrameBufferProperties() # props.set_rgb_color(True) # props.set_rgba_bits(8, 8, 8, 8) # props.set_depth_bits(8) # self.buff = self.graphicsEngine.make_output( # self.pipe, name, sort, # props, winprops, # GraphicsPipe.BF_resizeable, # self.win.get_gsg(), self.win) #self.screenTexture = render_pipeline._final_stage.target.color_tex #self.buff.addRenderTexture(self.screenTexture, GraphicsOutput.RTMCopyRam) # self.buff.set_sort(sort) #self.cam = self.makeCamera(self.buff) #self.render_pipeline._showbase.cam=self.makeCamera(self.buff) #self.render_pipeline._showbase.cam=self.makeCamera(self.buff) #self.render_pipeline._showbase.camera.reparentTo(self.render) #base.camera.reparentTo(self.render) #self.cam.reparentTo(self.render) # 可选同步 #render_pipeline.set_camera(self.cam) #添加渲染效果�� #self.cam = self.render_pipeline._showbase.cam #self.camNode = self.cam.node() #self.camLens = self.camNode.get_lens() self.render_pipeline._showbase.camera = self.render_pipeline._showbase.cam #self.render_pipeline.daytime_mgr.update() # if clear_color is None: # self.buff.set_clear_active(GraphicsOutput.RTPColor, False) # else: # self.buff.set_clear_color(clear_color) # self.buff.set_clear_active(GraphicsOutput.RTPColor, True) # self.disableMouse() self.mouse_controller = CustomMouseController(self) self.mouse_controller.setUp() def render_pipeline(self): """获取 RenderPipeline 实例""" return self._render_pipeline def set_parent(self, parent: QWidget): self.parent = parent self.mouseWatcherNode = QMouseWatcherNode(parent) def getAspectRatio(self, win = None): if win is None and self.parent is not None: return float(self.parent.width()) / float(self.parent.height()) else: return super().getAspectRatio(win) def get_render_pipeline(): """获取全局 RenderPipeline 单例""" if _global_render_pipeline is None: raise RuntimeError( "RenderPipeline has not been initialized yet. Please create a Panda3DWorld instance first.") return _global_render_pipeline def resize_buffer(self, width: int, height: int): """根据新窗口尺寸调整 Panda3D 渲染输出尺寸""" # 设置 Panda3D 的窗口尺寸(offscreen 模式下对应输出区域) props = WindowProperties() props.set_size(width, height) self.win.request_properties(props) # 重新分配输出贴图的大小 self.qt_output_tex.set_x_size(width) self.qt_output_tex.set_y_size(height) # 更新 lens 的 aspect ratio if self.camLens: self.camLens.set_film_size(width, height) # 或 set_aspect_ratio(width / height) # 强制更新窗口(有时在 Qt 内嵌时需要) self.graphicsEngine.open_windows()