175 lines
5.8 KiB
Python
175 lines
5.8 KiB
Python
#!/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基础测试完成!") |