#!/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("测试完成")