204 lines
6.8 KiB
Python
204 lines
6.8 KiB
Python
import warnings
|
||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||
|
||
from QPanda3D.Panda3DWorld import Panda3DWorld
|
||
from panda3d.core import (CardMaker, Vec4, Vec3, AmbientLight, DirectionalLight,
|
||
Point3, WindowProperties)
|
||
from direct.showbase.ShowBaseGlobal import globalClock
|
||
|
||
|
||
class CoreWorld(Panda3DWorld):
|
||
"""核心世界功能类 - 负责基础的3D世界设置和核心功能"""
|
||
|
||
def __init__(self):
|
||
super().__init__()
|
||
|
||
# 初始化基础属性
|
||
self.qtWidget = None # Qt部件引用(用于获取准确的渲染区域尺寸)
|
||
|
||
# 设置相机控制参数
|
||
self.cameraSpeed = 200.0 # 移动速度
|
||
self.cameraRotateSpeed = 40.0 # 旋转速度
|
||
|
||
# 鼠标控制相关变量
|
||
self.lastMouseX = 0
|
||
self.lastMouseY = 0
|
||
self.mouseRightPressed = False
|
||
|
||
# 初始化世界
|
||
self._setupCamera()
|
||
self._setupLighting()
|
||
self._setupGround()
|
||
self._loadFont()
|
||
|
||
print("✓ 核心世界初始化完成")
|
||
|
||
def _setupCamera(self):
|
||
"""设置相机位置和朝向"""
|
||
self.cam.setPos(0, -50, 20)
|
||
self.cam.lookAt(0, 0, 0)
|
||
print("✓ 相机设置完成")
|
||
|
||
def _setupLighting(self):
|
||
"""设置基础光照系统"""
|
||
# 环境光
|
||
alight = AmbientLight('alight')
|
||
alight.setColor((0.2, 0.2, 0.2, 1))
|
||
alnp = self.render.attachNewNode(alight)
|
||
self.render.setLight(alnp)
|
||
|
||
# 定向光(模拟太阳光)
|
||
dlight = DirectionalLight('dlight')
|
||
dlight.setColor((0.8, 0.8, 0.8, 1))
|
||
dlnp = self.render.attachNewNode(dlight)
|
||
dlnp.setHpr(45, -45, 0) # 设置光照方向
|
||
self.render.setLight(dlnp)
|
||
|
||
# 保存光源引用
|
||
self.ambient_light = alnp
|
||
self.directional_light = dlnp
|
||
|
||
print("✓ 光照系统设置完成")
|
||
|
||
def _setupGround(self):
|
||
"""创建地板"""
|
||
cm = CardMaker('ground')
|
||
cm.setFrame(-50, 50, -50, 50)
|
||
|
||
# 创建地板节点
|
||
self.ground = self.render.attachNewNode(cm.generate())
|
||
self.ground.setP(-90)
|
||
self.ground.setZ(-0.1)
|
||
self.ground.setColor(0.8, 0.8, 0.8, 1)
|
||
|
||
print("✓ 地板创建完成")
|
||
|
||
def _loadFont(self):
|
||
"""加载中文字体"""
|
||
try:
|
||
self.chinese_font = self.loader.loadFont('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc')
|
||
if not self.chinese_font:
|
||
print("警告: 无法加载中文字体,将使用默认字体")
|
||
else:
|
||
print("✓ 中文字体加载成功")
|
||
except:
|
||
print("警告: 无法加载中文字体,将使用默认字体")
|
||
self.chinese_font = None
|
||
|
||
def setQtWidget(self, widget):
|
||
"""设置Qt部件引用"""
|
||
self.qtWidget = widget
|
||
print(f"✓ 设置Qt部件引用: {widget}")
|
||
|
||
def getWindowSize(self):
|
||
"""获取准确的窗口尺寸"""
|
||
if self.qtWidget:
|
||
# 优先使用Qt部件的实际尺寸
|
||
width, height = self.qtWidget.getActualSize()
|
||
if width > 0 and height > 0:
|
||
return width, height
|
||
|
||
# 备用方案:使用Panda3D窗口尺寸
|
||
if hasattr(self, 'win') and self.win:
|
||
width = self.win.getXSize()
|
||
height = self.win.getYSize()
|
||
print(f"从Panda3D窗口获取尺寸: {width} x {height}")
|
||
return width, height
|
||
|
||
# 最后的默认值
|
||
print("使用默认窗口尺寸: 800 x 600")
|
||
return 800, 600
|
||
|
||
# ==================== 相机控制功能 ====================
|
||
|
||
def wheelForward(self, data=None):
|
||
"""处理滚轮向前滚动(前进)"""
|
||
# 获取相机的前向向量
|
||
forward = self.cam.getMat().getRow3(1)
|
||
# 计算移动距离
|
||
distance = self.cameraSpeed * globalClock.getDt()
|
||
# 更新相机位置
|
||
currentPos = self.cam.getPos()
|
||
newPos = currentPos + forward * distance
|
||
self.cam.setPos(newPos)
|
||
|
||
def wheelBackward(self, data=None):
|
||
"""处理滚轮向后滚动(后退)"""
|
||
# 获取相机的前向向量
|
||
forward = self.cam.getMat().getRow3(1)
|
||
# 计算移动距离
|
||
distance = self.cameraSpeed * globalClock.getDt()
|
||
# 更新相机位置
|
||
currentPos = self.cam.getPos()
|
||
newPos = currentPos - forward * distance
|
||
self.cam.setPos(newPos)
|
||
|
||
def moveCamera(self, x, y, z):
|
||
"""移动相机位置(垂直移动)"""
|
||
# 获取相机的上向量
|
||
upVector = self.cam.getMat().getRow3(2)
|
||
# 计算移动距离
|
||
distance = self.cameraSpeed * globalClock.getDt()
|
||
# 更新相机位置
|
||
currentPos = self.cam.getPos()
|
||
newPos = currentPos + upVector * z * distance
|
||
self.cam.setPos(newPos)
|
||
|
||
# ==================== 鼠标事件处理 ====================
|
||
|
||
def mousePressEventRight(self, evt):
|
||
"""处理鼠标右键按下事件"""
|
||
print("右键按下")
|
||
self.mouseRightPressed = True
|
||
self.lastMouseX = evt['x']
|
||
self.lastMouseY = evt['y']
|
||
|
||
def mouseReleaseEventRight(self, evt):
|
||
"""处理鼠标右键释放事件"""
|
||
print("右键释放")
|
||
self.mouseRightPressed = False
|
||
|
||
def mouseMoveEvent(self, evt):
|
||
"""处理鼠标移动事件 - 只处理相机旋转"""
|
||
if not evt:
|
||
return
|
||
|
||
if self.mouseRightPressed:
|
||
# 计算鼠标移动距离
|
||
dx = evt.get('x', 0) - self.lastMouseX
|
||
dy = evt.get('y', 0) - self.lastMouseY
|
||
|
||
# 计算旋转角度
|
||
rotateSpeed = self.cameraRotateSpeed * globalClock.getDt()
|
||
|
||
# 更新相机朝向
|
||
currentH = self.cam.getH()
|
||
currentP = self.cam.getP()
|
||
|
||
# 限制俯仰角度在-90到90度之间
|
||
newP = max(-90, min(90, currentP - dy * rotateSpeed))
|
||
|
||
self.cam.setH(currentH - dx * rotateSpeed)
|
||
self.cam.setP(newP)
|
||
|
||
# 更新鼠标位置
|
||
self.lastMouseX = evt.get('x', 0)
|
||
self.lastMouseY = evt.get('y', 0)
|
||
|
||
# ==================== 其他基础功能 ====================
|
||
|
||
def getChineseFont(self):
|
||
"""获取中文字体"""
|
||
return self.chinese_font
|
||
|
||
def getGroundNode(self):
|
||
"""获取地板节点"""
|
||
return self.ground
|
||
|
||
def getAmbientLight(self):
|
||
"""获取环境光"""
|
||
return self.ambient_light
|
||
|
||
def getDirectionalLight(self):
|
||
"""获取定向光"""
|
||
return self.directional_light |