建模 — 法线与切线
前置条件:先阅读 unreal-modeling。
库
CDO:/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions
TargetMesh 为 UDynamicMesh* 路径字符串。Debug 省略。需要 FGeometryScriptMeshSelection 的函数,用 MeshOperationLibrary 桥接。需要 FGeometryScriptVectorList 的函数,用 MakeVectorList/GetVectorListArray 桥接。
主要函数
法线计算
| 函数 |
关键参数 |
说明 |
SetPerVertexNormals |
TargetMesh |
平滑法线(无硬边) |
SetPerFaceNormals |
TargetMesh |
面法线(每条边都是硬边) |
RecomputeNormals |
TargetMesh, CalculateOptions, bDeferChangeNotifications |
保留已有分裂,重新计算法线 |
RecomputeNormalsForMeshSelection |
TargetMesh, Selection, CalculateOptions |
对选中区域重算法线 |
ComputeSplitNormals |
TargetMesh, SplitOptions, CalculateOptions |
按角度/Polygroup 重建分裂后重算法线 |
AutoRepairNormals |
TargetMesh |
修复不一致的法线方向(闭合 mesh 效果最佳) |
法线翻转
| 函数 |
关键参数 |
说明 |
FlipNormals |
TargetMesh |
翻转全部法线并反转三角形绕序 |
FlipTriangleSelectionNormals |
TargetMesh, Selection, bFlipTriangleOrientation, bFlipNormalDirection |
翻转选中区域法线 |
法线读写
| 函数 |
关键参数 |
说明 |
SetMeshTriangleNormals |
TargetMesh, TriangleID, Normals(FGeometryScriptTriangle) |
设置单个三角形三个角的法线。out:bIsValidTriangle |
SetMeshPerVertexNormals |
TargetMesh, VertexNormalList |
批量设置每顶点法线(列表大小 = MaxVertexID) |
GetMeshPerVertexNormals |
TargetMesh, bAverageSplitVertexValues |
out:NormalList、bIsValidNormalSet、bHasVertexIDGaps |
UpdateVertexNormal |
TargetMesh, VertexID, bUpdateNormal, NewNormal, bUpdateTangents, NewTangentX, NewTangentY |
更新单个顶点的法线和/或切线 |
SetSplitNormalsAlongSelectedEdges |
TargetMesh, Selection, bSplit, bRecalculateNormals, CalculateOptions |
沿选中边分裂/合并法线 |
切线
| 函数 |
关键参数 |
说明 |
ComputeTangents |
TargetMesh, Options |
计算切线(需要有效法线 + UV) |
SetMeshPerVertexTangents |
TargetMesh, TangentXList, TangentYList |
批量设置切线 |
GetMeshPerVertexTangents |
TargetMesh, bAverageSplitVertexValues |
out:TangentXList、TangentYList |
GetMeshHasTangents |
TargetMesh |
out:bHasTangents |
DiscardTangents |
TargetMesh |
移除切线层 |
结构体与枚举
FGeometryScriptCalculateNormalsOptions
| 字段 |
类型 |
默认值 |
说明 |
bAngleWeighted |
bool |
true |
按角度加权 |
bAreaWeighted |
bool |
true |
按面积加权 |
FGeometryScriptSplitNormalsOptions
| 字段 |
类型 |
默认值 |
说明 |
bSplitByOpeningAngle |
bool |
true |
按折痕角度分裂 |
OpeningAngleDeg |
float |
15 |
折痕角度阈值(度) |
bSplitByFaceGroup |
bool |
false |
按 Polygroup 边界分裂 |
GroupLayer |
FGeometryScriptGroupLayer |
默认层 |
Polygroup 层 |
FGeometryScriptTangentsOptions
| 字段 |
类型 |
默认值 |
说明 |
Type |
EGeometryScriptTangentTypes |
FastMikkT |
切线算法 |
UVLayer |
int |
0 |
用于计算切线的 UV 通道 |
EGeometryScriptTangentTypes
| 值 |
说明 |
FastMikkT |
快速 MikkT 切线 |
PerTriangle |
每三角形切线 |
StandardMikkT |
标准 MikkT(可能回退到 FastMikkT) |
JSON 示例
重算法线(保留分裂,面积+角度加权):
{"object":"/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions","function":"RecomputeNormals","params":{"TargetMesh":"/Engine/Transient.DynamicMesh_0","CalculateOptions":{"bAreaWeighted":true,"bAngleWeighted":true},"bDeferChangeNotifications":false}}
按角度分裂法线后重算:
{"object":"/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions","function":"ComputeSplitNormals","params":{"TargetMesh":"/Engine/Transient.DynamicMesh_0","SplitOptions":{"bSplitByOpeningAngle":true,"OpeningAngleDeg":60,"bSplitByFaceGroup":false},"CalculateOptions":{"bAreaWeighted":true,"bAngleWeighted":true}}}
计算切线(MikkT,UV 通道 0):
{"object":"/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions","function":"ComputeTangents","params":{"TargetMesh":"/Engine/Transient.DynamicMesh_0","Options":{"Type":"FastMikkT","UVLayer":0}}}
发现
对 CDO 路径调用 DescribeObject 可查看完整函数列表和参数签名。
1---2name: unreal-modeling-normals3description: GeometryScript 法线与切线操作。当用户要求重算法线、分裂法线、翻转法线、计算切线或修复法线方向时使用。4---56# 建模 — 法线与切线78前置条件:先阅读 `unreal-modeling`。910## 库1112CDO:`/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions`1314`TargetMesh` 为 `UDynamicMesh*` 路径字符串。`Debug` 省略。需要 `FGeometryScriptMeshSelection` 的函数,用 `MeshOperationLibrary` 桥接。需要 `FGeometryScriptVectorList` 的函数,用 `MakeVectorList`/`GetVectorListArray` 桥接。1516## 主要函数1718### 法线计算1920| 函数 | 关键参数 | 说明 |21|------|----------|------|22| `SetPerVertexNormals` | `TargetMesh` | 平滑法线(无硬边) |23| `SetPerFaceNormals` | `TargetMesh` | 面法线(每条边都是硬边) |24| `RecomputeNormals` | `TargetMesh`, `CalculateOptions`, `bDeferChangeNotifications` | 保留已有分裂,重新计算法线 |25| `RecomputeNormalsForMeshSelection` | `TargetMesh`, `Selection`, `CalculateOptions` | 对选中区域重算法线 |26| `ComputeSplitNormals` | `TargetMesh`, `SplitOptions`, `CalculateOptions` | 按角度/Polygroup 重建分裂后重算法线 |27| `AutoRepairNormals` | `TargetMesh` | 修复不一致的法线方向(闭合 mesh 效果最佳) |2829### 法线翻转3031| 函数 | 关键参数 | 说明 |32|------|----------|------|33| `FlipNormals` | `TargetMesh` | 翻转全部法线并反转三角形绕序 |34| `FlipTriangleSelectionNormals` | `TargetMesh`, `Selection`, `bFlipTriangleOrientation`, `bFlipNormalDirection` | 翻转选中区域法线 |3536### 法线读写3738| 函数 | 关键参数 | 说明 |39|------|----------|------|40| `SetMeshTriangleNormals` | `TargetMesh`, `TriangleID`, `Normals`(FGeometryScriptTriangle) | 设置单个三角形三个角的法线。out:`bIsValidTriangle` |41| `SetMeshPerVertexNormals` | `TargetMesh`, `VertexNormalList` | 批量设置每顶点法线(列表大小 = MaxVertexID) |42| `GetMeshPerVertexNormals` | `TargetMesh`, `bAverageSplitVertexValues` | out:`NormalList`、`bIsValidNormalSet`、`bHasVertexIDGaps` |43| `UpdateVertexNormal` | `TargetMesh`, `VertexID`, `bUpdateNormal`, `NewNormal`, `bUpdateTangents`, `NewTangentX`, `NewTangentY` | 更新单个顶点的法线和/或切线 |44| `SetSplitNormalsAlongSelectedEdges` | `TargetMesh`, `Selection`, `bSplit`, `bRecalculateNormals`, `CalculateOptions` | 沿选中边分裂/合并法线 |4546### 切线4748| 函数 | 关键参数 | 说明 |49|------|----------|------|50| `ComputeTangents` | `TargetMesh`, `Options` | 计算切线(需要有效法线 + UV) |51| `SetMeshPerVertexTangents` | `TargetMesh`, `TangentXList`, `TangentYList` | 批量设置切线 |52| `GetMeshPerVertexTangents` | `TargetMesh`, `bAverageSplitVertexValues` | out:`TangentXList`、`TangentYList` |53| `GetMeshHasTangents` | `TargetMesh` | out:`bHasTangents` |54| `DiscardTangents` | `TargetMesh` | 移除切线层 |5556## 结构体与枚举5758### `FGeometryScriptCalculateNormalsOptions`5960| 字段 | 类型 | 默认值 | 说明 |61|------|------|--------|------|62| `bAngleWeighted` | bool | `true` | 按角度加权 |63| `bAreaWeighted` | bool | `true` | 按面积加权 |6465### `FGeometryScriptSplitNormalsOptions`6667| 字段 | 类型 | 默认值 | 说明 |68|------|------|--------|------|69| `bSplitByOpeningAngle` | bool | `true` | 按折痕角度分裂 |70| `OpeningAngleDeg` | float | `15` | 折痕角度阈值(度) |71| `bSplitByFaceGroup` | bool | `false` | 按 Polygroup 边界分裂 |72| `GroupLayer` | `FGeometryScriptGroupLayer` | 默认层 | Polygroup 层 |7374### `FGeometryScriptTangentsOptions`7576| 字段 | 类型 | 默认值 | 说明 |77|------|------|--------|------|78| `Type` | `EGeometryScriptTangentTypes` | `FastMikkT` | 切线算法 |79| `UVLayer` | int | `0` | 用于计算切线的 UV 通道 |8081### `EGeometryScriptTangentTypes`8283| 值 | 说明 |84|----|------|85| `FastMikkT` | 快速 MikkT 切线 |86| `PerTriangle` | 每三角形切线 |87| `StandardMikkT` | 标准 MikkT(可能回退到 FastMikkT) |8889## JSON 示例9091**重算法线**(保留分裂,面积+角度加权):9293```json94{"object":"/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions","function":"RecomputeNormals","params":{"TargetMesh":"/Engine/Transient.DynamicMesh_0","CalculateOptions":{"bAreaWeighted":true,"bAngleWeighted":true},"bDeferChangeNotifications":false}}95```9697**按角度分裂法线后重算**:9899```json100{"object":"/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions","function":"ComputeSplitNormals","params":{"TargetMesh":"/Engine/Transient.DynamicMesh_0","SplitOptions":{"bSplitByOpeningAngle":true,"OpeningAngleDeg":60,"bSplitByFaceGroup":false},"CalculateOptions":{"bAreaWeighted":true,"bAngleWeighted":true}}}101```102103**计算切线**(MikkT,UV 通道 0):104105```json106{"object":"/Script/GeometryScriptingCore.Default__GeometryScriptLibrary_MeshNormalsFunctions","function":"ComputeTangents","params":{"TargetMesh":"/Engine/Transient.DynamicMesh_0","Options":{"Type":"FastMikkT","UVLayer":0}}}107```108109## 发现110111对 CDO 路径调用 `DescribeObject` 可查看完整函数列表和参数签名。