EG/demo/射线坐标系统修复说明.md
2025-07-10 09:19:51 +08:00

126 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 射线显示坐标系统修复说明
## 🔍 问题描述
用户发现射线显示时是从场景中心点射出,而不是从相机位置射出。这违反了鼠标点击射线的基本原理。
## ⚡ 问题原因
### 1. **坐标系混淆**
```python
# 原始错误代码
nearPoint = Point3()
farPoint = Point3()
self.world.cam.node().getLens().extrude(Point2(mx, my), nearPoint, farPoint)
# 直接使用相机坐标系的点显示射线(错误!)
self.showClickRay(nearPoint, farPoint, hitPos)
```
### 2. **坐标系不匹配**
- `lens.extrude()` 返回的是**相机坐标系**中的点
- 射线显示节点挂在 `render` 下,使用**世界坐标系**
- 直接使用相机坐标系的点会导致射线从错误位置显示
## 🛠 修复方案
### 1. **正确的坐标变换**
```python
# 获取相机坐标系中的射线点
nearPoint = Point3()
farPoint = Point3()
self.world.cam.node().getLens().extrude(Point2(mx, my), nearPoint, farPoint)
# 转换到世界坐标系用于显示
worldNearPoint = self.world.render.getRelativePoint(self.world.cam, nearPoint)
worldFarPoint = self.world.render.getRelativePoint(self.world.cam, farPoint)
# 使用世界坐标系的点显示射线
self.showClickRay(worldNearPoint, worldFarPoint, hitPos)
```
### 2. **碰撞检测保持不变**
```python
# 碰撞检测仍使用相机坐标系(正确!)
pickerNode = CollisionNode('mouseRay')
pickerNP = self.world.cam.attachNewNode(pickerNode) # 相机子节点
direction = farPoint - nearPoint
direction.normalize()
pickerNode.addSolid(CollisionRay(nearPoint, direction)) # 相机坐标系
```
## 📐 坐标系统详解
### **相机坐标系 vs 世界坐标系**
| 坐标系 | 用途 | 特点 |
|--------|------|------|
| 相机坐标系 | 碰撞检测 | 以相机为原点Z轴向前 |
| 世界坐标系 | 射线显示 | 以场景为原点,固定坐标 |
### **为什么需要不同坐标系?**
1. **碰撞检测**
- 碰撞节点是相机的子节点
- 使用相机坐标系可以跟随相机移动
- 射线方向相对于相机计算
2. **射线显示**
- 射线节点是render的子节点
- 需要在世界坐标系中显示固定位置
- 从相机真实位置到点击点
## 🎯 修复效果
### **修复前**
```
射线起点: (相机坐标系原点) = 场景中心附近
射线方向: 正确,但起点错误
显示效果: 射线从场景中心发射 ❌
```
### **修复后**
```
射线起点: (相机世界位置) = 真实相机位置
射线方向: 正确,指向鼠标点击方向
显示效果: 射线从相机位置发射 ✅
```
## 🧪 验证方法
1. **启动射线测试**
```bash
python demo/ray_display_test.py
```
2. **按R键开启射线显示**
3. **移动相机到不同位置**
4. **点击鼠标观察射线**
- 射线应该从当前相机位置开始
- 射线应该指向鼠标点击的方向
- 相机移动后射线起点应该跟随变化
## 📋 技术要点
### **关键API使用**
```python
# 获取相机坐标系中的射线
lens.extrude(screen_point, near_point, far_point)
# 坐标系转换
world_point = render.getRelativePoint(camera, camera_point)
# 反向转换
camera_point = camera.getRelativePoint(render, world_point)
```
### **调试输出**
现在会显示两套坐标:
```
相机坐标系射线起点: (0, 1, 0)
世界坐标系射线起点: (-15.2, -42.3, 18.7)
```
这样您就可以清楚地看到射线现在是从真实的相机位置发射,而不是从场景中心发射了!🎯