OBS Studio libobs 图形 API 详解:axisang(轴角表示)结构与四元数互转
OBS Studio libobs 图形 API 详解axisang轴角表示结构与四元数互转【免费下载链接】obs-studioOBS Studio - Free and open source software for live streaming and screen recording项目地址: https://gitcode.com/GitHub_Trending/ob/obs-studio本文基于 OBS Studio 官方 Sphinx 参考文档docs/sphinx/reference-libobs-graphics-axisang.rst完整讲解 libobs 图形模块中axisang轴角表示辅助结构体的成员布局与全部公开 API并结合 libobs/graphics/axisang.c、libobs/graphics/quat.c 等源码剖析轴角与四元数互转的数学实现、数值稳定性处理以及它在渲染矩阵变换管线中的真实调用链帮助读者在插件与滤镜开发中正确使用这一旋转表示。1. axisang 的定位libobs 旋转数据家族的一环在 OBS Studio 的底层图形库 libobs 中旋转数据主要通过三套类型表示四元数struct quatlibobs/graphics/quat.h、轴角struct axisang以及由二者生成的旋转矩阵struct matrix3/struct matrix4。axisang的定位非常明确——官方参考文档将其概括为 Provides a helper structure for conversion to quaternions即它是轴角表示axis-angle的辅助结构核心价值在于与四元数之间的相互转换轴角表示直观易懂一个旋转 一条单位轴 一个绕该轴转过的角度弧度四元数在插值和组合上更稳健quat.h头注释说明四元数用于表示旋转数据且插值时不受万向锁影响axisang因此承担人话接口的角色开发者按(x, y, z, angle)的直觉写入旋转再通过quat_from_axisang进入 libobs 的核心旋转运算体系。使用方式与文档一致直接包含头文件即可#include graphics/axisang.h注意libobs是 C 接口库头文件内含extern C保护见 libobs/graphics/axisang.hC 插件可直接调用。2. 结构体定义union 布局与成员语义文档描述的axisang结构在源码中的完整定义见 libobs/graphics/axisang.hstruct quat; struct axisang { union { struct { float x, y, z, w; }; float ptr[4]; }; };对照文档中的成员说明成员类型语义axisang.xfloat旋转轴的 X 分量axisang.yfloat旋转轴的 Y 分量axisang.zfloat旋转轴的 Z 分量axisang.wfloat旋转角度Angleaxisang.ptr[4]float[4]同一块内存的数组视图几个值得注意的源码细节x, y, z是轴w才是角度。这一点与四元数struct quatlibobs/graphics/quat.h的布局刻意保持一致——quat中w是标量分量而axisang中w被复用为角度便于两套表示在渲染代码中混用时心智模型统一。union ptr[4]的惯用手法。ptr提供把四个分量当作连续数组访问的能力例如与 SIMD 或按内存块拷贝的场景对接。这与struct quat中额外叠加__m128 m成员的做法一脉相承quat直接用 SSE 指令做四分量运算见quat_add、quat_mulf等内联函数而axisang没有引入__m128视图从源码结构看它是纯辅助结构、不参与高频运算。角度单位是弧度。从源码可以确认quat_from_axisang直接对w调用sinf(halfa)/cosf(halfa)见第 4 节调用方在需要角度制时显式使用 libobs/graphics/math-defs.h 中定义的RAD(val)/DEG(val)宏做转换例如RAD(90.0f)得到π/2。3. 四个 API 逐个讲解3.1axisang_zero清零文档签名void axisang_zero(struct axisang *dst)功能 Zeroes the axis angle。实现是头文件中的内联函数libobs/graphics/axisang.hstatic inline void axisang_zero(struct axisang *dst) { dst-x 0.0f; dst-y 0.0f; dst-z 0.0f; dst-w 0.0f; }清零后的轴角是零旋转的退化形态轴全零、角度为零。3.2axisang_copy拷贝文档签名void axisang_copy(struct axisang *dst, struct axisang *aa)功能 Copies an axis angle参数分别为拷贝目标dst与来源aa。实现libobs/graphics/axisang.hstatic inline void axisang_copy(struct axisang *dst, struct axisang *aa) { dst-x aa-x; dst-y aa-y; dst-z aa-z; dst-w aa-w; }逐分量赋值而非memcpy与quat_copy的风格一致调用方需注意dst与aa不可重叠源码未做别名保护属于 C 库的常见约定。3.3axisang_set一次性赋值文档签名void axisang_set(struct axisang *dst, float x, float y, float z, float w)功能 Sets an axis angle参数依次是目标、X 轴、Y 轴、Z 轴、角度。实现libobs/graphics/axisang.hstatic inline void axisang_set(struct axisang *dst, float x, float y, float z, float w) { dst-x x; dst-y y; dst-z z; dst-w w; }这是四个函数中最常用的一个libobs 内部大量调用点都是栈上临时构造一个轴角再立即使用的模式第 5 节会给出实例。3.4axisang_from_quat从四元数创建轴角文档签名void axisang_from_quat(struct axisang *dst, const struct quat *q)功能 Creates an axis angle from a quaternion参数为轴角目标dst与待转换四元数q。这是四个 API 中唯一编译进 libobs 动态库导出EXPORT而非头文件内联的函数实现位于 libobs/graphics/axisang.cvoid axisang_from_quat(struct axisang *dst, const struct quat *q) { float len, leni; len q-x * q-x q-y * q-y q-z * q-z; if (!close_float(len, 0.0f, EPSILON)) { leni 1.0f / sqrtf(len); dst-x q-x * leni; dst-y q-y * leni; dst-z q-z * leni; dst-w acosf(q-w) * 2.0f; } else { dst-x 0.0f; dst-y 0.0f; dst-z 0.0f; dst-w 0.0f; } }这段实现完整体现了轴角 四元数向量部分的方向 两倍的标量反余弦这一数学关系且有工程上值得学习的细节轴提取与归一化。四元数的向量部分(x, y, z)本身就平行于旋转轴其长度等于sin(θ/2)。代码先求平方和len再乘1/sqrt(len)完成归一化得到单位轴。角度恢复。dst-w acosf(q-w) * 2.0f利用了q.w cos(θ/2)即θ 2·acos(q.w)。近零旋转的退化分支。当len与 0 的差值小于EPSILON时单位四元数的恒等旋转w1, xyz0恰好落在此分支输出全零轴角避免对零向量做无意义的归一化。这里用到的工具定义在 libobs/graphics/math-defs.h#define EPSILON 1e-4f static inline bool close_float(float f1, float f2, float precision) { return fabsf(f1 - f2) precision; }即判据是|len - 0| 1e-4对应|sin(θ/2)| ≤ ~0.01也就是小于约 1.14° 的微小旋转统一视为零旋转。这是浮点安全设计若不做此判断恒等四元数会被转成轴不定的噪声值。4. 正向链路轴角如何变成四元数虽然axisang文档只描述了axisang_from_quat这一个转换方向但完整的往返链路里另一半quat_from_axisang是理解本结构体的关键它声明在 libobs/graphics/quat.h实现在 libobs/graphics/quat.cvoid quat_from_axisang(struct quat *dst, const struct axisang *aa) { float halfa aa-w * 0.5f; float sine sinf(halfa); dst-x aa-x * sine; dst-y aa-y * sine; dst-z aa-z * sine; dst-w cosf(halfa); }实现即教科书公式q (sin(θ/2)·axis, cos(θ/2))。两点实用结论轴需要调用方保证为单位向量。从源码看quat_from_axisang直接以aa-x/y/z乘以sine未做归一化这与axisang_from_quat会归一化形成不对称——可以推断由四元数转出的轴角总是单位轴而手工axisang_set写入的轴若不为单位向量生成的四元数长度将偏离 1需要自行注意。往返一致性依赖四元数为单位四元数这一前提axisang_from_quat的acosf(q-w)对非单位四元数会给出无意义结果。5. 调用链实证axisang 在 OBS 渲染管线中的位置从源码结构看axisang并非孤立结构它是渲染矩阵从轴角到旋转矩阵链路的入口。典型调用链为axisang_set() → quat_from_axisang() // libobs/graphics/quat.c → matrix3/4_from_axisang() // 经由 quat 生成旋转矩阵 → matrix*_rotate_aa() / gs_matrix_rotaa4f() // 乘入当前矩阵各环节的源码位置3x4 矩阵libobs/graphics/matrix3.h 导出matrix3_from_axisang、matrix3_rotate_aa并内联了四参数便捷函数matrix3.hstatic inline void matrix3_rotate_aa4f(struct matrix3 *dst, const struct matrix3 *m, float x, float y, float z, float rot) { struct axisang aa; axisang_set(aa, x, y, z, rot); matrix3_rotate_aa(dst, m, aa); }4x4 矩阵libobs/graphics/matrix4.h 提供matrix4_from_axisang、matrix4_rotate_aa后乘与matrix4_rotate_aa_i前乘及matrix4_rotate_aa4f。前/后乘之分对应不同的变换组合次序见 libobs/graphics/matrix4.cvoid matrix4_from_axisang(struct matrix4 *dst, const struct axisang *aa) { struct quat q; quat_from_axisang(q, aa); matrix4_from_quat(dst, q); }渲染主循环接口libobs/graphics/graphics.c 中的gs_matrix_rotaa把轴角右乘到当前顶点的 top matrix其四参数版本gs_matrix_rotaa4f则是axisang_set最典型的使用范式void gs_matrix_rotaa4f(float x, float y, float z, float angle) { struct matrix4 *top_mat; struct axisang aa; if (!gs_valid(gs_matrix_rotaa4f)) return; top_mat top_matrix(thread_graphics); if (top_mat) { axisang_set(aa, x, y, z, angle); matrix4_rotate_aa_i(top_mat, aa, top_mat); } }注意两处防御gs_valid检查图形子系统是否就绪top_matrix判空保证在无渲染上下文的线程中调用不会崩溃。真实调用点可作为使用范例直接参考异步视频源的旋转渲染libobs/obs-source.c 在处理带旋转的异步源时先平移再绕 Z 轴旋转角度由度数经RAD宏转为弧度gs_matrix_translate3f(x, y, 0); gs_matrix_rotaa4f(0.0f, 0.0f, -1.0f, RAD((float)rotation));预览窗口选择手柄的绘制frontend/widgets/OBSBasicPreview.cpp 中围绕手柄中心旋转绘制同样走gs_matrix_rotaa4f(0, 0, 1, RAD(rot))的路径配合gs_matrix_push/pop保存恢复矩阵栈。注视方向四元数构造libobs/graphics/quat.c 的quat_set_look_dir内部用axisang_set分别构造绕 Y 轴的偏航与绕 X 轴的俯仰两个轴角再各自quat_from_axisang合成最终朝向展示了轴角作为中间量构造四元数的复合用法。6. 工程要点小结结合文档与源码使用axisang时可归纳为四个 API 的分工axisang_zero/axisang_set负责初始化axisang_copy负责传递axisang_from_quat负责从四元数逆向提取轴角前三个为头文件内联函数libobs/graphics/axisang.h后者为库导出符号libobs/graphics/axisang.c在 libobs/CMakeLists.txt 的构建目标中graphics/axisang.c计入私有源文件而graphics/axisang.h计入public_headers对外安装。单位约定w分量是弧度角度x, y, z建议为单位轴向量quat_from_axisang不做归一化。数值边界小于EPSILON1e-4见 libobs/graphics/math-defs.h的旋转分量在axisang_from_quat中会被归零输出这是刻意的稳定化设计测试或比较轴角结果时应考虑这一阈值。适用场景需要轴 角这种人类可读的旋转描述时如 UI 角度滑块、场景变换的旋转角用axisang建模随后交给quat_from_axisang或matrix*_from_axisang进入 libobs 的标准旋转管线而高频插值与组合运算则直接使用struct quat其头部注释明确说明四元数用于避免万向锁的旋转插值。7. 延伸阅读路径四元数完整 APIdocs/sphinx/reference-libobs-graphics-quat.rst、libobs/graphics/quat.h矩阵接口含from_axisang/rotate_aa系列docs/sphinx/reference-libobs-graphics-matrix4.rst、libobs/graphics/matrix4.h、libobs/graphics/matrix3.h图形子系统总览与gs_matrix_*矩阵接口docs/sphinx/reference-libobs-graphics-graphics.rst、libobs/graphics/graphics.h图形模块文档入口docs/sphinx/graphics.rst【免费下载链接】obs-studioOBS Studio - Free and open source software for live streaming and screen recording项目地址: https://gitcode.com/GitHub_Trending/ob/obs-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →