1
0
forked from Rowland/EG
EG/QPanda3D/Panda3DWorld.py
2025-09-28 16:08:22 +08:00

202 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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)
#添加渲染效果<E69588><E69E9C>
#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()