·
编程学习 ·
154936
在执行背面消除之前,要先进行物体剔除(Object Removal)。
可以使用包围球测试来剔除物体,对每个物体,创建一个将其包围起来的球体,并判断球体是否位于视景体内。
通过找出离物体中心最远的顶点,可以算出该顶点与物体中心的距离,即为包围球的半径。
计算出包围球半径后,可以定义6个点,它们与球心的连线分别平行于±x轴,±y轴,±z轴,这些点定义了包围球。
先考虑2D的包围圆,下图是y=0y=0y=0平面的俯视图:
-
p1是包围圆圆心,坐标为(x1,z1)(x_1,z_1)(x1,z1)
-
p2是+z轴方向的最远端点,坐标为(x1,z1+r)(x_1,z_1+r)(x1,z1+r)
-
p3是+z轴方向的最近端点,坐标为(x1,z1−r)(x_1,z_1-r)(x1,z1−r)
-
p4是+x轴方向的最远端点,坐标为(x1+r,z1)(x_1+r,z_1)(x1+r,z1)
-
p5是+x轴方向的最近端点,坐标为(x1−r,z1)(x_1-r,z_1)(x1−r,z1)
物体剔除原理:如果这些点都位于视景体外,则包围圆完全位于视景体外。
z轴方向的剔除条件:
(p2.z<far_z)∣∣(p3.z>near_z)(p2.z < far\_z) || (p3.z > near\_z)(p2.z<far_z)∣∣(p3.z>near_z)
即:(z1+r<far_z)∣∣(z1−r>near_z)(z_1+r < far\_z) || (z_1-r > near\_z)(z1+r<far_z)∣∣(z1−r>near_z)
x轴方向则需要通过平面方程和p4,p5两个端点的位置来判断。
根据上图可得,
视景体右平面的平面方程:x=w/2dzx=\frac{w/2}{d}zx=dw/2z
视景体左平面的平面方程:x=−w/2dzx=-\frac{w/2}{d}zx=−dw/2z
最终可得,
x轴方向的剔除条件:
(p5.x>w/2dp5.z)∣∣(p4.x<−w/2dp4.z)(p5.x > \frac{w/2}{d}p5.z) || (p4.x < -\frac{w/2}{d}p4.z)(p5.x>dw/2p5.z)∣∣(p4.x<−dw/2p4.z)
即:
(x1−r>w/2dz1)∣∣(x1+r<−w/2dz1)(x_1-r > \frac{w/2}{d}z_1) || (x_1+r < -\frac{w/2}{d}z_1)(x1−r>dw/2z1)∣∣(x1+r<−dw/2z1)
同理拓展到球心坐标为(x1,y1,z1)(x_1, y_1, z_1)(x1,y1,z1)的3D包围球,可得y轴方向的剔除条件:
(y1−r>w/2dz1)∣∣(y1+r<−w/2dz1)(y_1-r > \frac{w/2}{d}z_1) || (y_1+r < -\frac{w/2}{d}z_1)(y1−r>dw/2z1)∣∣(y1+r<−dw/2z1)
只要满足任意一轴的剔除条件,即可判断包围球在视景体外,综上,给定物体包围球球心坐标(x1,y1,z1)(x_1, y_1, z_1)(x1,y1,z1)、和相机参数(视平面宽度www,视距ddd,***面距离near_znear\_znear_z和远平面距离far_zfar\_zfar_z),物体被剔除的条件为:
(z1+r<far_z)∣∣(z1−r>near_z)∣∣(x1−r>w/2dz1)∣∣(x1+r<−w/2dz1)∣∣(y1−r>w/2dz1)∣∣(y1+r<−w/2dz1)
\begin{aligned}
&(z_1+r < far\_z) || (z_1-r > near\_z)\\
&||(x_1-r > \frac{w/2}{d}z_1) || (x_1+r < -\frac{w/2}{d}z_1)\\
&||(y_1-r > \frac{w/2}{d}z_1) || (y_1+r < -\frac{w/2}{d}z_1)
\end{aligned}
(z1+r<far_z)∣∣(z1−r>near_z)∣∣(x1−r>dw/2z1)∣∣(x1+r<−dw/2z1)∣∣(y1−r>dw/2z1)∣∣(y1+r<−dw/2z1)
物体剔除运行效果:
完整代码详见:https://github.com/maijiaquan/gdi-soft-render
参考资料:
- 《3D游戏编程大师技巧》
本文介绍如何使用requests+BeautifulSoup配合正则清洗,从嵌入JavaScript的混淆HTML表格中稳定提取内的商品名称(如FEIJAOCARIOCAURBAN),解决换行符、制表符及转义序列干扰导致的解析失败问题。 本文介绍如何使用requests+beautifulsoup配...
Tk字体度量结果天然跨平台不一致,因Tk版本升级、系统后端差异及Python绑定层未做标准化所致;应避免预计算宽度,改用渲染后回读或运行时补偿。 字体度量计算逻辑随Tk版本升级而变更 Tkinter本身不直接渲染字体,而是调用底层Tk库的fontmetrics和fontmeasure接口。从Tk8....
Jinja2无法直接遍历PandasDataFrame对象,需先将其转换为字典列表(如to_dict('records')),才能在HTML模板中通过{%for%}正确访问字段值。 jinja2无法直接遍历pandasdataframe对象,需先将其转换为字典列表(如`to_dict('record...
cached.Loader不生效通常是配置位置错误,它必须作为包装器嵌套配置,将其他loader置于其参数列表中,而非与之并列;其缓存位于进程内存,依赖文件修改时间,重启服务才能刷新,且与Django的CACHES设置无关。 cached.Loader不生效,八成是配置写错了位置,不是缓存没起作用,...
tf.image.non_max_suppression返回的是被选中边界框在输入boxes中的整数下标,需配合tf.gather等操作提取对应坐标、分数和类别;它不支持多类别联合抑制,须按类别分组处理,并注意GPU未实现该算子、坐标需统一归一化等关键约束。 为什么tf.image.non_max_...
cached.Loader未生效主因是配置错误:必须将其严格嵌套为['django.template.loaders.cached.Loader',['loader1','loader2']]结构,否则仅包装首个loader;其缓存键依赖模板路径与st_mtime,mtime不变或未重启进程将导致缓...
本文介绍在Python中使用Jinja2渲染YAML模板时,多行字符串(如|块标量)被错误转义为带换行符的单引号字符串的问题,并推荐使用ruamel.yaml替代PyYAML实现保真解析与输出。 本文介绍在python中使用jinja2渲染yaml模板时,多行字符串(如`|`块标量)被错误转义为带换...
本文详解PyYAML在解析含|多行字面量字符串时丢失格式的问题,推荐使用ruamel.yaml替代方案,确保Jinja2渲染后YAML结构(尤其是|块标量)完整保留,并提供可落地的代码示例与最佳实践。 本文详解pyyaml在解析含`|`多行字面量字符串时丢失格式的问题,推荐使用`ruamel.yam...