EG/demo/ray_offset_debug.py
2025-07-02 09:49:59 +08:00

116 lines
4.4 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from direct.showbase.ShowBase import ShowBase
from panda3d.core import (
Point3, Point2, Vec3, CollisionTraverser, CollisionHandlerQueue,
CollisionNode, CollisionRay, CollisionSphere, BitMask32
)
class RayOffsetDebug(ShowBase):
def __init__(self):
ShowBase.__init__(self)
# 使用和主程序相同的相机设置
self.cam.setPos(-3.87655, -188.38084, 82.602684)
self.cam.lookAt(0, 0, 0)
print("=== 射线偏移调试 ===")
print(f"相机位置: {self.cam.getPos()}")
print(f"相机朝向: {self.cam.getHpr()}")
# 显示镜头参数
lens = self.cam.node().getLens()
print(f"镜头FOV: {lens.getFov()}")
print(f"宽高比: {lens.getAspectRatio()}")
# 设置射线检测
self.setupRayPicking()
# 测试不同位置的射线
self.testRayDirections()
print("调试完成")
def setupRayPicking(self):
"""设置射线检测"""
self.pickerNode = CollisionNode('mouseRay')
self.pickerRay = CollisionRay()
self.pickerNode.addSolid(self.pickerRay)
mask = BitMask32.bit(0)
self.pickerNode.setFromCollideMask(mask)
self.pickerNode.setIntoCollideMask(BitMask32.allOff())
self.pickerNP = self.render.attachNewNode(self.pickerNode)
def testRayDirections(self):
"""测试不同位置的射线方向"""
print("\n=== 射线方向测试 ===")
# 模拟不同的屏幕点击位置
test_cases = [
(0.0, 0.0, "屏幕中心"),
(-0.5, 0.0, "屏幕左侧"),
(0.5, 0.0, "屏幕右侧"),
(0.0, 0.5, "屏幕上方"),
(0.0, -0.5, "屏幕下方"),
(-0.006, 0.346, "用户点击位置"),
]
for norm_x, norm_y, description in test_cases:
print(f"\n--- {description}: ({norm_x:.3f}, {norm_y:.3f}) ---")
# 使用setFromLens方法
success = self.pickerRay.setFromLens(self.cam.node(), norm_x, norm_y)
if success:
rayOrigin = self.pickerRay.getOrigin()
rayDirection = self.pickerRay.getDirection()
print(f"射线起点: {rayOrigin}")
print(f"射线方向: {rayDirection}")
# 分析相机坐标系中的分量
camForward = self.cam.getMat().getRow3(1)
camRight = self.cam.getMat().getRow3(0)
camUp = self.cam.getMat().getRow3(2)
forwardComp = rayDirection.dot(camForward)
rightComp = rayDirection.dot(camRight)
upComp = rayDirection.dot(camUp)
print(f"相机坐标系分量:")
print(f" 前向: {forwardComp:.6f}")
print(f" 右向: {rightComp:.6f} (正=右, 负=左)")
print(f" 上向: {upComp:.6f} (正=上, 负=下)")
# 计算射线与(0,10,3)点的交点(地面上的一个点)
targetPoint = Point3(0, 10, 3)
rayToTarget = targetPoint - rayOrigin
# 检查射线是否指向这个方向
if rayDirection.dot(rayToTarget) > 0:
# 计算交点
distance = rayToTarget.length()
angle = rayDirection.dot(rayToTarget.normalized())
print(f"与参考点(0,10,3)的角度: {angle:.6f}")
# 预测射线在y=10平面上的交点
if abs(rayDirection.getY()) > 0.001:
t = (10 - rayOrigin.getY()) / rayDirection.getY()
if t > 0:
intersectionPoint = rayOrigin + rayDirection * t
print(f"在Y=10平面上的交点: {intersectionPoint}")
else:
print("射线不指向Y=10平面")
else:
print("射线平行于Y=10平面")
else:
print("射线背离参考点")
else:
print("setFromLens 失败")
if __name__ == "__main__":
app = RayOffsetDebug()
print("测试完成")