opengl 矩阵投影代码 shade_LookAt、Viewport、Perspective矩阵

6606882bc07ffaec8e88bc3d037ba650.png

LookAt 矩阵

OpenGL本身没有摄像机(Camera)的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动。

lookat矩阵是由这些东西来定义的:摄像头位置,它看向的方向,以及向上的up方向。由于“OpenGL中我们知道摄像机指向z轴负方向”,所以给图如下:

f02fcb6a2f829e850699c6d9893bab56.png

那么我们知道实际上坐标系的方向是这样的,我们用(eye - center)就能得到z轴的方向,然后我们定义一个向上的方向

,我们可以用
- 向上的方向叉乘z得到x方向,再用
- z方向叉乘x得到y.

8523e72c7793a9d9551b3887908c145b.png

也可以参考这个图:

b8f566c9ddf398c22e2111a664a90e98.png

再根据之前的坐标变换知识,于是我们可以得到lookat矩阵:

  • R - 右向量,也就是相机坐标系x在世界坐标系中的表示
  • U - 上向量,也就是相机坐标系y在世界坐标系中的表示
  • D - 方向向量,也就是相机坐标系z在世界坐标系中的表示
  • P - 相机在世界坐标系中位置

我感觉也可以这样理解,Rotation、Translation其实是相机在世界坐标系中的变换:

其实我们用它来看物体也就是它这个变换的逆变换:

而相机的旋转矩阵的逆是它的转置,平移矩阵的逆也可以在就是把它移回去,这样也跟上面的lookat矩阵一样。写个代码:

void 

Viewport 矩阵

我们再来求另一个常见矩阵,我们现在有模型都在[-1,1]*[-1,1]*[-1,1]正方体中,我们想把它映射到位置[x,x+w]*[y,y+h]*[0,d]中,我们的操作是:

  • 平移:先把[-1,1]*[-1,1]*[-1,1]平移到[0,2]*[0,2]*[0,2]
  • 缩放:[0,2]*[0,2]*[0,2]缩放到[0,1]*[0,1]*[0,1]
  • 缩放:[0,1]*[0,1]*[0,1]缩放到[0,w]*[0,h]*[0,d]
  • 平移:[0,w]*[0,h]*[0,d]移动到[x,x+w]*[y,y+h]*[0,d]

就跟窗口变换十分类似,我们可以来求得这个变换的矩阵:

计算得:

这个矩阵是OpenGL中的Viewport矩阵。

Perspective 矩阵

投影有两种:

正交:

b5e6061f4ed3f6e29021283644f33db0.png

透视:

d6b100166eb5662f1f515c2d2602a0c2.png

我们都知道透视法则-近大远小,就像上图,平行的铁路公路在我们的眼睛里也是会在远处相交的。

1263f5de91ca365966a31fdf08faede9.png

如果我们要将P点投影到 z=0 平面上的 P' 点,camera放在C点(0, 0, c),很容易可以按照比例算出 |AB|/|AC| = |OD|/|OC| 可知: x/(c-z) = x'/c,可知:

所以我们也可以得到投影矩阵:

参考:

  • 摄像机
  • 坐标系统
  • glViewport
  • Perspective projection
<think>我们正在处理一个关于Python枚举循环的问题。用户的问题描述是:"我想理解或调试 Python代码中的枚举循环请问Pythonfor loopwith enumeratestring_nofactor inshade_factors"。看起来用户可能在处理一个涉及字符串枚举的循环,并且提到了"shade_factors",但问题描述不够清晰。 由于用户的问题比较模糊,我们可能需要先解释一下Python中`enumerate`的基本用法,然后尝试猜测用户可能遇到的问题。`enumerate`用于在循环中同时获取索引元素。例如:```pythonforindex,char inenumerate("hello"):print(index,char)``` 输出: 0h1e2 l3l4 o用户提到“string_nofactor inshade_factors”,这可能意味着用户有一个字符串(string_no)一个列表(shade_factors),并试图在循环中使用枚举。但具体问题不明。我们可能需要引导用户提供更多信息,但既然要求生成回答,我们可以先给出一个通用的枚举循环示例,并解释如何调试。另外,用户的问题中可能有拼写错误或表述不清,比如“string_no”可能是一个变量名,“shade_factors”可能是另一个变量。假设用户想要遍历一个字符串,并根据索引从另一个列表(shade_factors)中获取因子来执行某些操作。 示例代码:```pythonstring_no= "ABCDE"shade_factors= [0.1,0.2,0.3,0.4,0.5]foridx, charin enumerate(string_no):factor =shade_factors[idx]#根据索引获取对应的因子#然后使用charfactor做一些操作print(f"字符{char}对应的因子是 {factor}")``` 但是,如果字符串的长度shade_factors列表的长度不一致,则会引发索引错误。这可能是用户遇到的问题之一。 调试建议: 1.检查两个变量的长度是否一致。2.在循环中添加打印语句,查看每一步的值。3.使用try-except捕获可能的异常。如果用户的问题是关于枚举循环中处理两个序列,我们也可以使用`zip`函数: ```pythonfor (idx, char), factorin zip(enumerate(string_no), shade_factors):#或者更简单:for char, factorin zip(string_no, shade_factors):print(idx, char, factor) ```由于问题描述不够详细,我们只能提供一般性帮助。根据要求,我们需要生成相关问题。因此,在回答之后,我们将生成几个相关问题。 现在,我们按照要求组织回答:</think>### Python枚举循环调试指南 在Python中,`enumerate()`函数用于在循环中同时获取元素的索引值,特别适用于需要操作索引的场景。对于您提到的`string_no``shade_factors`,以下是调试分析枚举循环的关键步骤: #### 1. **基本枚举循环结构** ```python for index, char in enumerate(string_no): # 当前字符 = char # 当前索引 = index # 可在此处访问 shade_factors[index] ``` #### 2. **常见调试点** - **索引越界问题** 当`shade_factors`长度小于`string_no`时: ```python # 安全访问方式 factor = shade_factors[index] if index < len(shade_factors) else None ``` - **类型不匹配问题** 添加类型检查: ```python if not isinstance(shade_factors, list): print(f"错误:shade_factors应是列表,实际是{type(shade_factors)}") ``` - **空值处理** 使用`try-except`捕获异常: ```python try: current_factor = shade_factors[index] except IndexError: print(f"索引 {index} 超出shade_factors范围") ``` #### 3. **完整调试示例** ```python string_no = "abc123" shade_factors = [0.2, 0.5, 0.8] # 示例数据 print("调试开始:") for i, char in enumerate(string_no): print(f"迭代{i}: 字符={char}", end=" | ") # 安全访问shade_factors if i < len(shade_factors): factor = shade_factors[i] print(f"shade_factor={factor}") # 此处添加业务逻辑 else: print("shade_factor: 索引超出范围") print("调试结束") ``` #### 4. **输出分析** ``` 调试开始: 迭代0: 字符=a | shade_factor=0.2 迭代1: 字符=b | shade_factor=0.5 迭代2: 字符=c | shade_factor=0.8 迭代3: 字符=1 | shade_factor: 索引超出范围 迭代4: 字符=2 | shade_factor: 索引超出范围 迭代5: 字符=3 | shade_factor: 索引超出范围 调试结束 ``` #### 5. **优化建议** - 使用`zip`处理等长序列: ```python for (i, char), factor in zip(enumerate(string_no), shade_factors): # 自动处理索引对齐 ``` - 添加断言检查: ```python assert len(string_no) == len(shade_factors), "两个序列长度不匹配" ``` ### 关键问题排查清单 1. 检查`string_no``shade_factors`的数据类型 2. 验证两个序列的长度关系 3. 检查索引计算逻辑是否包含边界值 4. 确认`shade_factors`是否包含`None`或非法值 5. 在循环内打印关键变量实时值 > 提示:使用IDE的调试工具(如VSCode/PyCharm断点功能)可逐步跟踪变量变化[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值