第4章 几何物体建模:标准几何体与布尔运算

好,我们进入非序列光线追迹的实操第一步——建物体。

很多人觉得建模不就是画个球、拉个方块嘛,有什么好讲的?

但我在项目里见过太多人,因为一个圆柱体的方向没搞对,追迹结果差了十万八千里。或者布尔运算切错了顺序,整个系统得重来。

这一章,咱们就把标准几何体和布尔运算彻底讲透。

4.1 标准几何体:球体、立方体、圆柱体

Code V 的非序列模式下,几何体是通过 OBJECT 命令配合 TYPE 参数来定义的。我习惯先把物体类型想清楚,再填参数,这样不容易乱。

4.1.1 球体(Sphere)

球体是最简单的。你只需要一个球心位置和半径。

! 创建一个半径为 10 mm 的球体,球心在 (0,0,0)
OBJECT 1
  TYPE SPHERE
  RADIUS 10.0
  POSITION 0.0 0.0 0.0
END

这里有个坑:球体的表面法线方向默认朝外。如果你想让光线从球内部射向表面(比如模拟气泡),需要把法线反转。我当年做微透镜阵列时,就因为这个搞反了,追迹结果全是全反射,折腾了一下午。

注意:球体的 RADIUS 不能为负值。如果需要凹面效果,请使用 TYPE SPHERE 配合 REVERSE 关键字。

4.1.2 立方体(Box)

立方体需要定义三个方向的尺寸:X、Y、Z 方向的半边长。

! 创建一个 20x10x5 mm 的长方体,中心在 (0,0,0)
OBJECT 2
  TYPE BOX
  X_HALF 10.0
  Y_HALF 5.0
  Z_HALF 2.5
  POSITION 0.0 0.0 0.0
END

注意,这里给的是半边长,不是全长。很多新手直接填全长,结果物体比预期大一倍。我建议你在注释里写清楚「全长=20」,免得回头自己都忘了。

4.1.3 圆柱体(Cylinder)

圆柱体稍微复杂一点。除了半径和长度,你还要指定它的轴向。

! 创建一个半径为 5 mm、长度为 20 mm 的圆柱体,轴向为 Z
OBJECT 3
  TYPE CYLINDER
  RADIUS 5.0
  LENGTH 20.0
  DIRECTION 0.0 0.0 1.0
  POSITION 0.0 0.0 -10.0
END

DIRECTION 是单位向量,表示圆柱的轴线方向。我习惯把圆柱的起点放在 POSITION,然后沿 DIRECTION 延伸 LENGTH。这样定位比较直观。

小技巧:如果你需要圆锥或圆台,可以用 TYPE CONE,参数类似,只是多了一个顶部半径。

4.2 参数设置的核心逻辑

其实所有标准几何体的参数设置,都遵循一个共同逻辑:位置 + 形状 + 方向。我整理了一个对照表,方便你快速查阅。

几何体 位置参数 形状参数 方向参数
球体 POSITION (x,y,z) RADIUS 无(各向同性)
立方体 POSITION (x,y,z) X_HALF, Y_HALF, Z_HALF 无(默认与坐标轴对齐)
圆柱体 POSITION (x,y,z) RADIUS, LENGTH DIRECTION (dx,dy,dz)
圆锥体 POSITION (x,y,z) RADIUS1, RADIUS2, LENGTH DIRECTION (dx,dy,dz)

你想想看,只要掌握了这个逻辑,任何标准几何体都能快速上手。说白了就是三个问题:放哪?多大?朝哪?

4.3 布尔运算:合并与切割

单个几何体太简单了,实际光学系统里很少有纯粹的球或方块。你需要把多个几何体组合起来——这就是布尔运算。

Code V 的布尔运算通过 COMPOSITE 物体类型来实现。支持三种操作:UNION(合并)、INTERSECTION(交集)、SUBTRACTION(切割)。我们重点讲合并和切割,因为这两个最常用。

4.3.1 合并(UNION)

合并就是把两个或多个物体粘在一起,变成一个整体。光线追迹时,Code V 会把它们当作一个物体来处理。

! 创建一个复合物体:球体 + 圆柱体
OBJECT 10
  TYPE COMPOSITE
  OPERATION UNION
  OBJECT 1  ! 球体
  OBJECT 3  ! 圆柱体
END

合并时要注意:两个物体的材料必须相同。如果材料不同,Code V 会报错。我遇到过有人想把玻璃透镜和金属支架合并,结果怎么都跑不通——后来才意识到,不同材料不能合并,得用多个物体分别定义。

4.3.2 切割(SUBTRACTION)

切割是从一个物体中挖掉另一个物体。这个在建模透镜、棱镜、反射镜时特别有用。

! 从立方体中挖掉一个球体,形成一个凹坑
OBJECT 20
  TYPE COMPOSITE
  OPERATION SUBTRACTION
  OBJECT 2  ! 被切割的物体(立方体)
  OBJECT 1  ! 切割工具(球体)
END

这里有个顺序问题:第一个物体是被切的,第二个是切刀。搞反了的话,你会得到一个空壳子。我曾经在做一个非球面透镜的挖槽时,顺序写反了,追迹结果全是零,查了半天才发现是布尔运算的顺序错了。

核心原则:布尔运算的物体必须都是实体(SOLID),不能是面或线。如果你用曲面去切割实体,Code V 会直接忽略这个操作。

4.4 布尔运算的避坑指南

布尔运算看起来简单,但实际用起来坑不少。我总结了几条经验,你记一下。

  • 物体必须相交:如果两个物体没有重叠区域,合并就是两个独立物体,切割则无效。Code V 不会报错,但结果不是你想要的。
  • 避免零厚度:切割时,如果切刀刚好与被切物体表面相切,会产生零厚度的边缘。这会导致追迹时出现数值不稳定。我建议让切刀稍微深入一点。
  • 嵌套限制:Code V 允许布尔运算嵌套,比如先合并再切割。但嵌套层数太多时,计算会变慢。我一般控制在 3 层以内。
  • 调试方法:如果布尔运算结果不对,先用 DRAW 命令看看物体形状。可视化是最直接的调试手段。
警告:布尔运算后的复合物体,不能再作为其他布尔运算的切割工具。也就是说,你不能用一个复合物体去切另一个复合物体。这是 Code V 的限制。

4.5 知识体系图

下面这张图把本章的核心逻辑串起来了。你可以把它当作一个快速索引。

几何物体建模知识体系 几何物体建模 标准几何体 布尔运算 球体 立方体 圆柱体 合并 (UNION) 切割 (SUB) 交集 (INT) 核心原则 位置 + 形状 + 方向 = 标准几何体 布尔运算:材料相同、物体相交、顺序正确

4.6 实战案例:做一个简单的透镜模型

光说不练假把式。我们用一个实际案例把今天的内容串起来。

假设你要做一个平凸透镜:一面是平面(立方体切出来的),一面是球面。怎么做?

  1. 创建圆柱体:作为透镜的基底,半径 10 mm,厚度 5 mm。
  2. 创建球体:半径 20 mm,球心位置在圆柱体上方 15 mm 处(这样球面刚好凸出来)。
  3. 布尔运算切割:用球体去切圆柱体,得到凸面。
  4. 再切一次:用另一个平面(大立方体)切掉多余的部分,得到平的面。
! 步骤1:圆柱体基底
OBJECT 1
  TYPE CYLINDER
  RADIUS 10.0
  LENGTH 5.0
  DIRECTION 0.0 0.0 1.0
  POSITION 0.0 0.0 -2.5
END

! 步骤2:球体(切割工具)
OBJECT 2
  TYPE SPHERE
  RADIUS 20.0
  POSITION 0.0 0.0 15.0
END

! 步骤3:第一次切割,得到凸面
OBJECT 3
  TYPE COMPOSITE
  OPERATION SUBTRACTION
  OBJECT 1
  OBJECT 2
END

! 步骤4:平面切割工具(大立方体)
OBJECT 4
  TYPE BOX
  X_HALF 20.0
  Y_HALF 20.0
  Z_HALF 10.0
  POSITION 0.0 0.0 -12.0
END

! 步骤5:第二次切割,得到平面
OBJECT 5
  TYPE COMPOSITE
  OPERATION SUBTRACTION
  OBJECT 3
  OBJECT 4
END

嗯,这里要注意:第二次切割时,OBJECT 3 已经是复合物体了。Code V 允许复合物体作为被切割对象,但不能作为切割工具。所以这个流程是合法的。

调试建议:每做完一步,都用 DRAW OBJECT 1 看看形状对不对。别等到最后一步才发现中间错了,那时候改起来很麻烦。

好了,这一章的内容就到这里。标准几何体和布尔运算,是 Code V 非序列建模的基石。你把这些练熟了,后面做复杂系统就会顺手很多。