#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from direct.showbase.ShowBase import ShowBase
from panda3d.core import (
    Point3, Vec3, CollisionTraverser, CollisionHandlerQueue,
    CollisionNode, CollisionRay, CollisionSphere, BitMask32
)

class BasicRayTest(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        print("=== 基础射线测试 ===")
        
        # 简单的相机设置
        self.cam.setPos(0, -20, 5)
        self.cam.lookAt(0, 0, 0)
        
        print(f"相机位置: {self.cam.getPos()}")
        
        # 创建简单的碰撞球体在原点
        self.createSimpleSphere()
        
        # 创建简单的射线检测
        self.createSimpleRay()
        
        # 测试简单的射线
        self.testSimpleRay()
    
    def createSimpleSphere(self):
        """在原点创建简单的碰撞球体"""
        print(f"\n创建测试球体...")
        
        # 创建碰撞节点
        collisionNode = CollisionNode('testSphere')
        
        # 创建球体，中心在原点，半径5
        sphere = CollisionSphere(Point3(0, 0, 0), 5.0)
        collisionNode.addSolid(sphere)
        
        # 设置掩码
        collisionNode.setIntoCollideMask(BitMask32.bit(0))
        collisionNode.setFromCollideMask(BitMask32.allOff())
        
        # 附加到render
        self.sphereNP = self.render.attachNewNode(collisionNode)
        
        # 显示碰撞体
        self.sphereNP.show()
        
        print(f"球体创建在原点: (0, 0, 0)")
        print(f"球体半径: 5.0")
        print(f"球体 IntoMask: {collisionNode.getIntoCollideMask()}")
    
    def createSimpleRay(self):
        """创建简单的射线检测"""
        print(f"\n创建射线检测...")
        
        # 创建遍历器和队列
        self.traverser = CollisionTraverser()
        self.queue = CollisionHandlerQueue()
        
        # 创建射线节点
        rayNode = CollisionNode('testRay')
        self.ray = CollisionRay()
        rayNode.addSolid(self.ray)
        
        # 设置射线掩码
        rayNode.setFromCollideMask(BitMask32.bit(0))
        rayNode.setIntoCollideMask(BitMask32.allOff())
        
        # 创建射线节点路径
        self.rayNP = self.render.attachNewNode(rayNode)
        
        # 注册到遍历器
        self.traverser.addCollider(self.rayNP, self.queue)
        
        print(f"射线 FromMask: {rayNode.getFromCollideMask()}")
        print(f"遍历器中的碰撞器数量: {self.traverser.getNumColliders()}")
    
    def testSimpleRay(self):
        """测试简单的射线"""
        print(f"\n=== 射线测试 ===")
        
        # 测试1: 从相机直接射向原点
        camera_pos = self.cam.getPos()
        target_pos = Point3(0, 0, 0)
        
        direction = target_pos - camera_pos
        direction.normalize()
        
        print(f"测试1: 从相机射向原点")
        print(f"  起点: {camera_pos}")
        print(f"  方向: {direction}")
        
        # 设置射线
        self.ray.setOrigin(camera_pos)
        self.ray.setDirection(direction)
        
        # 执行检测
        self.queue.clearEntries()
        self.traverser.traverse(self.render)
        
        entries = self.queue.getNumEntries()
        print(f"  检测到 {entries} 个碰撞")
        
        if entries > 0:
            self.queue.sortEntries()
            for i in range(entries):
                entry = self.queue.getEntry(i)
                hitPos = entry.getSurfacePoint(self.render)
                hitNode = entry.getIntoNodePath()
                distance = (hitPos - camera_pos).length()
                print(f"    碰撞 {i}: {hitNode.getName()}, 距离: {distance:.2f}")
        
        # 测试2: 从固定位置射向球体
        print(f"\n测试2: 从固定位置射向球体")
        fixed_origin = Point3(-10, 0, 0)
        fixed_direction = Vec3(1, 0, 0)  # 直接向右
        
        print(f"  起点: {fixed_origin}")
        print(f"  方向: {fixed_direction}")
        
        self.ray.setOrigin(fixed_origin)
        self.ray.setDirection(fixed_direction)
        
        self.queue.clearEntries()
        self.traverser.traverse(self.render)
        
        entries = self.queue.getNumEntries()
        print(f"  检测到 {entries} 个碰撞")
        
        if entries > 0:
            self.queue.sortEntries()
            for i in range(entries):
                entry = self.queue.getEntry(i)
                hitPos = entry.getSurfacePoint(self.render)
                hitNode = entry.getIntoNodePath()
                distance = (hitPos - fixed_origin).length()
                print(f"    碰撞 {i}: {hitNode.getName()}, 距离: {distance:.2f}")
        
        # 测试3: 检查射线是否正确设置
        print(f"\n测试3: 检查射线设置")
        print(f"  射线起点: {self.ray.getOrigin()}")
        print(f"  射线方向: {self.ray.getDirection()}")
        
        # 手动计算射线是否应该击中球体
        origin = self.ray.getOrigin()
        direction = self.ray.getDirection()
        sphere_center = Point3(0, 0, 0)
        sphere_radius = 5.0
        
        # 计算从射线起点到球心的向量
        to_sphere = sphere_center - origin
        
        # 计算射线上最接近球心的点
        t = to_sphere.dot(direction)
        closest_point = origin + direction * t
        
        # 计算最近距离
        distance_to_center = (closest_point - sphere_center).length()
        
        print(f"  到球心的最近距离: {distance_to_center:.2f}")
        print(f"  球体半径: {sphere_radius:.2f}")
        
        if distance_to_center <= sphere_radius:
            print(f"  射线应该击中球体！")
        else:
            print(f"  射线会错过球体")

if __name__ == "__main__":
    app = BasicRayTest()
    print("\n基础测试完成！") 