SpaceMath 空间数学库使用手册
概要介绍
SpaceMath 是一个用于三维空间平移和旋转的 C 语言数学库,面向图形学、机器人、航空航天姿态解算与运动仿真等场景。库围绕三维向量、三阶旋转矩阵、四元数、欧拉角和轴角五种数据类型,提供从基础向量/矩阵运算、旋转表示构造与逆旋转,到表示间相互转换、旋转复合与作用的完整接口,共 211 个函数。
借助 SpaceMath,开发者可以用一致的调用风格完成任意姿态表示下的旋转计算,不必自行推导四元数乘法顺序、欧拉转序或矩阵存储约定等易错细节,从而专注于上层算法与应用实现。
源码仓库地址:https://github.com/scilogyhunter/SpaceMath
相关博客地址:https://blog.csdn.net/scilogyhunter/category_13092682.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=13092682&sharerefer=PC&sharesource=ScilogyHunter&sharefrom=from_link
功能概览
- 五种数据类型,多视图访问:
vec3_st、axis_st、eula_st、quat_st、mat3_st 均以联合体同时提供具名成员视图与数组视图,同一份数据既可按 x/y/z、w、s、roll/pitch/yaw、m11…m33 访问,也可按 v[]、vv[][]、v3[] 访问。 - 三档浮点精度,一处切换:由
CFG_FLOATWORD_BITSIZE 统一选择 32/64/128 位,ftype_t 类型、常量宏与数学函数宏随之整体切换。 - 完备的旋转表示互转:轴角、欧拉角、旋转矩阵、四元数两两可直接转换,共 12 条接口;另有 4 个显式指定转序的转换接口(
rotation_e2m_order 等)、4 个由向量对求旋转的接口(rotation_vv2a/e/m/q)和 4 个相对旋转接口(rotation_aa2a、ee2e、mm2m、qq2q)。 - 完备的旋转复合与作用:可以用任一种表示去旋转任一种表示或三维向量,即
rotation_XRY(X 为旋转的表示、Y 为被旋转的对象)共 4×5 = 20 个接口,无需先绕道转换成“中间表示”。 - 向量全量基础运算:48 个接口覆盖判等判零(含自定义容差)、点积与夹角、模长与距离、(含标量的)加减乘除、符号与取负绝对值、取整与环绕、极值与多形态钳制、叉积、单位化、投影、平面滑移、反射、绕轴旋转(罗德里格斯公式)、线性插值与三/四次贝塞尔插值。
- 矩阵全量基础运算:39 个接口覆盖判零/判单位/判对称/判正交/判对角、行列式、迹、范数、条件数、转置、求逆、取负、加减乘除与缩放(含缩放矩阵构造)、矩阵指数/对数/幂、绕轴基本旋转矩阵、线性插值与施密特正交归一化。
- 四元数全量基础运算:38 个接口覆盖判零判等、点积与模长、夹角、三种向量旋转实现(标准/快速/分量)、加减乘除、共轭、逆、归一化、连续性校正、幂、由轴角或向量对构造、线性插值与球面插值、绕轴基本旋转、导数与积分,可由角速度直接驱动姿态递推。
- 数值安全的实现:
safe_asin/safe_acos 夹紧定义域避免产生 NaN,safe_atan2 做除零保护;quat_continuous 消除四元数双重覆盖(q 与 -q 表示同一旋转)导致的插值跳变,quat_slerp 保证恒定角速度;mat3_orthonormalization 先做线性无关性预检查,退化输入返回原矩阵而非 NaN;mat3_cond 让使用者可判断求逆结果的可靠程度。全库比较统一走 MEPSILON 容差,而非直接使用 ==。 - 全接口单元测试覆盖,可一键自动化验证:库的每个接口都有对应的单元测试,测试模块与库源文件一一对应,另含随机旋转运算的随机化验证,合计 215 个测试用例;测试容差随浮点精度自适应(32 位
1e-3、64 位 1e-8、128 位 1e-12),三档精度下均可自动验证。测试程序支持 -v(详细输出)、-e(打印误差值)、-h(帮助)选项,自动汇总总用例数、通过数与通过率,全部通过返回 0、存在失败返回非零,便于接入持续集成。
设计思路
三维向量、旋转矩阵、四元数、欧拉角和轴角这些量的数学公式实现并不复杂,很多应用自行实现所需算法,也有不少功能全面的开源数学库可用。但"能用"和"好用"是两个差别很大的概念:自实现的模块往往不规范、功能不全面,甚至存在算法错误,也难在其他项目中复用;现成的通用库又常常过于庞大、缺乏针对性,移植成本高。基于对算法与需求的既有理解,以及一些蠢蠢欲动的新想法和对漂亮代码的偏执,特开发了此数学库,重点解决三个问题——约定容易混乱、功能边界不完整、数值细节不稳健。
为此,库确立了以下几条全局设计约定:
- 统一的浮点类型与常量体系。 精度由
CFG_FLOATWORD_BITSIZE 一处配置,ftype_t 是唯一的浮点类型名;所有常量宏按配置取值,MFLOAT_C(c) 保证字面量类型与当前精度一致,MFABS、MSQRT、MATAN2 等数学宏按精度映射到 fabsf/fabs/fabsl 等实现。切换精度只需改一行宏,所有调用点无需改动,从根本上杜绝 float 与 double 混用导致的隐式转换与精度损失。 - 统一的类型表示与多视图访问。 五种类型都以结构体承载语义,成员名即含义;同时以联合体保留数组视图,便于与外部数组数据(文件、总线、第三方库)零成本互操作。枚举
MINDEX_* 为数组下标提供具名索引,避免魔法数字。旋转矩阵采用列优先存储,与数学书写惯例一致,且同一列元素在内存中连续,按列访问及矩阵乘向量时 cache 命中更好。 - 统一的欧拉角转序配置。 默认转序由
CFG_EULER_ORDER 全局指定,可选 "xyz"、"xzy"、"yxz"、"yzx"、"zxy"、"zyx" 六种;全局使用一致转序可避免多转序混用导致的隐蔽错误,同时简化参数配置。确需在局部使用其它转序时,可用 rotation_e2m_order、rotation_m2e_order、rotation_e2q_order、rotation_q2e_order 直接指定,兼顾简洁与灵活。 - 值语义的接口形态。 除按数组构造的
*_v/*_vv 接口外,入参与返回值均为结构体值,没有指针参数,也无需空指针检查;调用可级联书写,例如 vec3_unit(vec3_rotate(v, axis, angle))、quat_normalize(quat_mul(q0, q1))。 - 统一的命名规约。 类型以单字母编码(
a 轴角、e 欧拉角、m 旋转矩阵、q 四元数、v 向量),旋转接口统一为 rotation_XRY,rotation_qRv 一眼可读出“用四元数旋转向量”;*_v/*_vv 表示按数组构造,*_order 表示显式指定转序,*_eps 表示自定义容差。签名自解释,不读文档也能正确调用。 - 实现与测试同步。 每个接口在实现的同时编写单元测试,库源文件与测试源文件一一对应,接口与用例同步演进;测试可一键自动运行并输出统计结果,使功能调整、精度切换和重构都有回归保障。
不追求过度的通用性——那会增加传参与实现的复杂度、降低易用性。库只解决空间平移与旋转线性计算这一类问题,并把这类问题的接口做到完整、明确、不易误用。
为什么用结构体而不是数组
使用结构体而非数组来表示三维向量、三维旋转矩阵、四元数、欧拉角和轴角,主要有以下考虑。
- 可读性更好,成员名本身就是文档。
结构体成员名直接表达含义,q.w、q.x、axis.angle 比 q[0]、a[3] 直观得多,阅读者不必反复查约定,也不必依赖注释确认下标含义。结构体是封闭的对象化表示,数组则把内部布局直接暴露给使用者。 - 消除顺序歧义与对应错误。
如果是数组表示,三维向量中v[0]、v[1]、v[2] 分别对应 x、y、z 轴的坐标可能不容易出错。但对于四元数,v[0]和v[3] 哪个是常量?三维旋转矩阵是行优先还是列优先? 轴角中,a[0] 和 a[3] 哪个是角度?实际情况是不同顺序约定都有库在使用,极容易搞混淆。经验表明,容易出错的地方就一定会出错。成员名把含义强制写清楚,至少在本库内部形成稳定、明确的语义,降低跨模块、跨团队协作时的沟通与出错成本。 - 避免越界访问。
数组下标写错就会越界读写,甚至导致程序崩溃;结构体成员由编译器按名字解析,不存在“下标越界”问题,可显著减少这类低级但危险的错误。 - 避免类型错判。
五种类型若都用数组表示,类型信息随之丢失,容易错判,并因各类型长度不同而级联导致越界访问。 - 可直接赋值。
同类型结构体之间可直接写 a = b;,数组则必须借助 memcpy 或循环赋值。按值传参使函数内部获得独立副本,调用者的数据不会被意外修改,局部性、可重入性与并发安全性更好。 - 便于类型检查与接口约束。
参数要求 quat_st 时,传入 vec3_st 或 mat3_st 会被编译器发现;数组因底层类型相近,容易在编译期蒙混过关,把错误推迟到运行期。 - 便于实现级联调用。
接口以传值方式输入输出,可以像数学公式一样层层嵌套,一行完成多级运算。例如把两个姿态 q0、q1 复合出旋转,归一化后旋转向量 v,再单位化,最后与参考方向 vref 求夹角,直接用本库接口写成:ftype_t a = vec3_angle(vec3_unit(rotation_qRv(quat_normalize(quat_mul(q0, q1)), v)), vref);
这行代码读起来与数学式子完全一致,没有中间变量,也就没有中间变量用错的可能。若接口改为数组传参的实现,同样的计算既无法嵌套,又必须为每一步准备具名临时数组,代码会繁杂很多:
ftype_t qm[4], qn[4], vr[3], vn[3];
quat_mul_arr(q0a, q1a, qm);
quat_normalize_arr(qm, qn);
rotation_qRv_arr(qn, va, vr);
vec3_unit_arr(vr, vn);
ftype_t a = vec3_angle_arr(vn, vrefa);
五步运算变成五行代码加四个临时数组,参数顺序错一处就不易察觉;级联写法只需一行,结果的类型与层次一目了然。外部数据本来就是数组时也不受影响:本库的 vec3_v()、quat_v()、mat3_v()、mat3_vv() 只负责“从数组构造”,在数据边界处转换一次即可进入级联,例如
ftype_t a = vec3_angle(vec3_unit(rotation_qRv(quat_normalize(q), vec3_v(pa))), vref);
- 性能未必有损失。
这类小对象(3~9 个标量)通常能被编译器充分优化,更容易命中 cache,也利于寄存器分配与内联,按值传递往往比想象中更高效。
配置选项
SpaceMath 库提供以下配置选项,可以通过修改这些宏来调整库的行为:
| 宏名称 | 描述 | 默认值 |
|---|
CFG_FLOATWORD_BITSIZE | 浮点数字长配置,支持32,64,128位 | 64 |
CFG_EULER_ORDER | 默认欧拉角旋转顺序,有效值包括:“xyz”,“xzy”,“yxz”,“yzx”,“zxy”,“zyx” | “yxz” |
注意:
CFG_FLOATWORD_BITSIZE 用于配置浮点数的位数,支持32,64,128位三种类型。注意x86架构下128位浮点数实际只有80位精度,存储空间同样为16字节。CFG_EULER_ORDER 用于配置默认的欧拉角旋转顺序,通过字符串表示,必须由小写xyz字母组成,长度固定为3字符,从左向右来表示按哪个轴来旋转。本库当前默认转序为"yxz",如需改用其他默认转序,可以修改CFG_EULER_ORDER宏。如果是临时使用非默认转序,可以使用rotation_e2m_order、rotation_m2e_order、rotation_e2q_order和rotation_q2e_order函数来实现,直接指定所需转序。
数据类型表格
| 单字母符号 | 英文全称 | 类型名称 | 成员 | 中文名称 | 描述 |
|---|
| V | vector 3D | vec3_st | x, y, z 或 v[3] | 三维向量 | 表示三维空间中的一个点或方向,有x、y、z三个分量 |
| A | axis-angle | axis_st | v3 (旋转轴), angle (旋转角度) 或 v[4] | 轴角 | 有axis和angle两个分量,axis为单位向量表示旋转轴,angle表示旋转角度 |
| E | euler angles | eula_st | x, y, z 或 roll, pitch, yaw 或 v[3] | 欧拉旋转角 | 是一个伪三维向量,分别表示绕x、y、z三轴的旋转角度,内旋模式,默认转序由CFG_EULER_ORDER配置(当前为"yxz") |
| Q | quaternion | quat_st | x, y, z, w 或 v3 (向量部分), s (标量部分) 或 v[4] | 四元数 | 旋转四元数,有x、y、z、w四个分量 |
| M | matrix | mat3_st | m11-m33 或 v[9] 或 vv[3][3] 或 v3[3] | 旋转矩阵 | 三阶正交方阵,或方向余弦矩阵(DCM) |
定义宏表格
SpaceMath 库根据 CFG_FLOATWORD_BITSIZE 配置提供不同的常量定义。以下表格展示不同浮点位数配置下的常量值:
常量宏
| 宏名称 | 描述 | 32位 | 64位 | 128位 |
|---|
MPI | 圆周率π的近似值 | 3.1415926536f | 3.14159265358979323846 | 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899L |
MPI2 | 2π的近似值 | 6.2831853072f | 6.28318530717958647692 | 6.28318530717958647692528676655900576839433879875021164194988918461563281257241799L |
MPI_2 | π/2的近似值 | 1.5707963268f | 1.57079632679489661923 | 1.57079632679489661923132169163975144209858469968755291048747229615390820314310449L |
MPI_4 | π/4的近似值 | 0.7853981634f | 0.78539816339744830962 | 0.78539816339744830961566084581987572104929234984377645524373614807695410157155224L |
M1_PI | 1/π的近似值 | 0.3183098862f | 0.31830988618379067154 | 0.31830988618379067153776752674502872406891929148091289749533468811779359526845307L |
M2_PI | 2/π的近似值 | 0.6366197724f | 0.63661977236758134308 | 0.63661977236758134307553505349005744813783858296182579499066937623558719053690614L |
M2_SQRTPI | 2/√π的近似值 | 1.1283791671f | 1.12837916709551257390 | 1.12837916709551257389615890312154517168810125865799771368817144342128493688298504L |
ME | 自然对数e的近似值 | 2.7182818285f | 2.71828182845904523536 | 2.71828182845904523536028747135266249775724709369995957496696762772407663035354759L |
MLOG2E | log2(e)的近似值 | 1.4426950409f | 1.44269504088896340735 | 1.44269504088896340735992468100189213742664595415298593413544940692110921993432412L |
MLOG10E | log10(e)的近似值 | 0.4342944819f | 0.43429448190325182765 | 0.43429448190325182765112891891660508229439700580366656611445378316586464920887077L |
MLN2 | ln(2)的近似值 | 0.6931471806f | 0.69314718055994530941 | 0.69314718055994530941723212145817656807550013436025525412068000949339362196969471L |
MLN10 | ln(10)的近似值 | 2.3025850930f | 2.30258509299404568402 | 2.30258509299404568401799145468436420760110148862877297603332790096757260967735248L |
MSQRT2 | √2的近似值 | 1.4142135624f | 1.41421356237309504880 | 1.41421356237309504880168872420969807856967187537694807317667973799073247846210703L |
MSQRT1_2 | 1/√2的近似值 | 0.7071067812f | 0.70710678118654752440 | 0.70710678118654752440084436210484903928483593768847403658833986899536623923105351L |
MEPSILON | 浮点数精度容差 | FLT_EPSILON | DBL_EPSILON | LDBL_EPSILON |
MRAD2DEG | 弧度转角度系数 | 180.0f / MPI | 180.0 / MPI | 180.0L / MPI |
MDEG2RAD | 角度转弧度系数 | MPI / 180.0f | MPI / 180.0 | MPI / 180.0L |
MFLOAT_C(c) | 浮点数常量宏 | c ## f | c | c ## L |
数学函数宏
以下宏根据浮点位数配置自动映射到相应的数学函数:
| 宏名称 | 描述 | 32位函数 | 64位函数 | 128位函数 |
|---|
MFABS | 绝对值函数 | fabsf | fabs | fabsl |
MFMIN | 最小值函数 | fminf | fmin | fminl |
MFMAX | 最大值函数 | fmaxf | fmax | fmaxl |
MSQRT | 平方根函数 | sqrtf | sqrt | sqrtl |
MSIN | 正弦函数 | sinf | sin | sinl |
MCOS | 余弦函数 | cosf | cos | cosl |
MACOS | 反余弦函数 | acosf | acos | acosl |
MASIN | 反正弦函数 | asinf | asin | asinl |
MTAN | 正切函数 | tanf | tan | tanl |
MATAN | 反正切函数 | atanf | atan | atanl |
MATAN2 | 反正切函数 | atan2f | atan2 | atan2l |
MPOW | 幂函数 | powf | pow | powl |
MFLOOR | 向下取整函数 | floorf | floor | floorl |
MCEIL | 向上取整函数 | ceilf | ceil | ceill |
MROUND | 四舍五入函数 | roundf | round | roundl |
MTRUNC | 截断函数 | truncf | trunc | truncl |
MFMOD | 取模函数 | fmodf | fmod | fmodl |
MREMAINDER | 余数函数 | remainderf | remainder | remainderl |
MCOPYSIGN | 符号函数 | copysignf | copysign | copysignl |
API函数表格
辅助函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
safe_is_equal | 判断两个浮点数是否相等(使用默认容差) | a, b: 要比较的浮点数 | 如果两个浮点数在容差范围内相等则返回true |
safe_is_equal_eps | 判断两个浮点数是否相等(使用自定义容差) | a, b: 要比较的浮点数, epsilon: 容差值 | 如果两个浮点数在指定容差范围内相等则返回true |
safe_is_zero | 判断浮点数是否为零(使用默认容差) | a: 要检查的浮点数 | 如果浮点数在容差范围内为零则返回true |
safe_asin | 安全arcsin函数,限制输入在[-1,1]范围内 | x: 输入值 | 对应的反正弦值(弧度) |
safe_acos | 安全arccos函数,限制输入在[-1,1]范围内 | x: 输入值 | 对应的反余弦值(弧度) |
safe_atan2 | 有除零保护的反正切函数 | y: 分子值, x: 分母值 | 对应的反正切值(弧度) |
轴角函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
axis_is_zero | 判断轴角是否为零轴角 | a: 要检查的轴角 | 如果角度接近零或旋转轴为零向量则返回true |
axis | 创建轴角结构体 | x, y, z: 旋转轴分量, angle: 旋转角度 | 创建的轴角结构体 |
axis_v | 通过数组创建轴角结构体 | v[4]: 包含四个元素的数组(前三个为旋转轴,第四个为旋转角度) | 创建的轴角结构体 |
axis_from_vector_angle | 由旋转轴向量和角度创建轴角结构体 | v3: 旋转轴向量, a: 旋转角度 | 创建的轴角结构体 |
axis_zero | 创建零轴角 | 无 | 零旋转的轴角 |
axis_from_vv | 由两个向量计算旋转轴角 | from: 起始向量, to: 目标向量 | 将from旋转到to所需的轴角 |
欧拉角函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
eula_validate | 验证旋转顺序字符串是否有效 | e: 欧拉角, order: 旋转顺序字符串 | 如果旋转顺序有效则返回true |
eula_is_zero | 检查欧拉角是否为零欧拉角 | e: 要检查的欧拉角 | 如果所有角度分量都接近零则返回true |
eula | 创建欧拉角结构体 | x, y, z: 绕各轴的旋转角度 | 创建的欧拉角结构体 |
eula_v | 通过数组创建欧拉角结构体 | v[3]: 包含三个角度分量的数组 | 创建的欧拉角结构体 |
eula_zero | 创建零欧拉角 | 无 | 所有分量为0.0的欧拉角 |
eula_add | 欧拉角加法 | e0, e1: 要相加的欧拉角 | 两个欧拉角的和 |
eula_sub | 欧拉角减法 | e0, e1: 要相减的欧拉角 | 两个欧拉角的差 |
eula_deg2rad | 将欧拉角从角度转换为弧度 | deg: 角度表示的欧拉角 | 弧度表示的欧拉角 |
eula_rad2deg | 将欧拉角从弧度转换为角度 | rad: 弧度表示的欧拉角 | 角度表示的欧拉角 |
eula_remainder | 欧拉角范围规范化到[-range, range] | e: 输入的欧拉角, range: 规范化范围 | 规范化后的欧拉角 |
矩阵函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
mat3_is_zero | 判断矩阵是否为零矩阵 | m: 要检查的矩阵 | 如果所有元素都接近零则返回true |
mat3_is_one | 判断矩阵是否为单位矩阵 | m: 要检查的矩阵 | 如果矩阵是单位矩阵则返回true |
mat3_is_identity | 判断矩阵是否为单位矩阵 | m: 要检查的矩阵 | 如果矩阵是单位矩阵则返回true |
mat3_is_symmetric | 判断矩阵是否为对称矩阵 | m: 要检查的矩阵 | 如果矩阵是对称矩阵则返回true |
mat3_is_orthogonal | 判断矩阵是否为正交矩阵 | m: 要检查的矩阵 | 如果矩阵是正交矩阵则返回true |
mat3_is_diagonal | 判断矩阵是否为对角矩阵 | m: 要检查的矩阵 | 如果矩阵是对角矩阵则返回true |
mat3_is_equal | 判断两个矩阵是否相等 | m0, m1: 要比较的矩阵 | 如果两个矩阵的所有元素都接近相等则返回true |
mat3_det | 计算矩阵的行列式 | m: 输入的矩阵 | 矩阵的行列式值 |
mat3_trace | 计算矩阵的迹 | m: 输入的矩阵 | 矩阵的迹(对角线元素之和) |
mat3_norm | 计算矩阵的范数 | m: 输入的矩阵, norm_type: 范数类型 | 矩阵的范数值 |
mat3_cond | 计算矩阵的条件数 | m: 输入的矩阵 | 矩阵的条件数 |
mat3_mul_vec | 矩阵与向量相乘 | m: 输入的矩阵, v: 输入的向量 | 矩阵与向量的乘积 |
mat3 | 创建矩阵结构体 | m11-m33: 矩阵元素 | 创建的矩阵结构体 |
mat3_v | 通过数组创建矩阵结构体 | v[9]: 包含九个元素的数组 | 创建的矩阵结构体 |
mat3_vv | 通过二维数组创建矩阵结构体 | vv[3][3]: 包含九个元素的二维数组 | 创建的矩阵结构体 |
mat3_zero | 创建零矩阵 | 无 | 所有元素为0.0的矩阵 |
mat3_one | 创建全1矩阵 | 无 | 所有元素为1.0的矩阵 |
mat3_identity | 创建单位矩阵 | 无 | 单位矩阵 |
mat3_transpose | 计算矩阵的转置 | m: 输入的矩阵 | 转置矩阵 |
mat3_inverse | 计算矩阵的逆 | m: 输入的矩阵 | 逆矩阵 |
mat3_negate | 计算矩阵的负矩阵 | m: 输入的矩阵 | 负矩阵 |
mat3_add | 矩阵加法 | m0, m1: 要相加的矩阵 | 两个矩阵的和 |
mat3_add_f | 矩阵与标量加法 | m: 输入的矩阵, f: 标量值 | 矩阵与标量的和 |
mat3_sub | 矩阵减法 | m0, m1: 要相减的矩阵 | 两个矩阵的差 |
mat3_sub_f | 矩阵与标量减法 | m: 输入的矩阵, f: 标量值 | 矩阵与标量的差 |
mat3_mul | 矩阵乘法 | m0, m1: 要相乘的矩阵 | 两个矩阵的乘积 |
mat3_mul_f | 矩阵与标量乘法 | m: 输入的矩阵, f: 标量值 | 矩阵与标量的乘积 |
mat3_scale | 矩阵缩放 | m: 输入的矩阵, scalar: 缩放因子 | 缩放后的矩阵 |
mat3_scale_matrix | 创建缩放矩阵 | sx, sy, sz: 各轴缩放因子 | 缩放矩阵 |
mat3_exp | 计算矩阵的指数 | m: 输入的矩阵 | 矩阵的指数 |
mat3_log | 计算矩阵的对数 | m: 输入的矩阵 | 矩阵的对数 |
mat3_pow | 计算矩阵的幂 | m: 输入的矩阵, exponent: 指数 | 矩阵的幂 |
mat3_rotation_x | 创建绕X轴旋转的矩阵 | f: 旋转角度 | 绕X轴旋转的矩阵 |
mat3_rotation_y | 创建绕Y轴旋转的矩阵 | f: 旋转角度 | 绕Y轴旋转的矩阵 |
mat3_rotation_z | 创建绕Z轴旋转的矩阵 | f: 旋转角度 | 绕Z轴旋转的矩阵 |
mat3_lerp | 矩阵线性插值 | from, to: 起始和结束矩阵, t: 插值因子 | 插值后的矩阵 |
mat3_orthonormalization | 矩阵正交归一化 | basis: 输入的基矩阵 | 正交归一化后的矩阵 |
向量函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
vec3_is_zero | 判断向量是否为零向量 | v: 要检查的向量 | 如果所有分量都接近零则返回true |
vec3_is_zero_eps | 判断向量是否为零向量(使用自定义容差) | v: 要检查的向量, epsilon: 容差值 | 如果所有分量都接近零则返回true |
vec3_is_equal | 判断两个向量是否相等 | v0, v1: 要比较的向量 | 如果两个向量的所有分量都接近相等则返回true |
vec3_is_equal_eps | 判断两个向量是否相等(使用自定义容差) | v0, v1: 要比较的向量, epsilon: 容差值 | 如果两个向量的所有分量都接近相等则返回true |
vec3_is_linear_independent | 判断三个向量是否线性无关 | v0, v1, v2: 要检查的向量 | 如果三个向量线性无关则返回true |
vec3_dot | 计算两个向量的点积 | v0, v1: 要计算点积的向量 | 两个向量的点积 |
vec3_angle | 计算两个向量之间的角度 | v0, v1: 要计算角度的向量 | 两个向量之间的角度(弧度) |
vec3_len | 计算向量的模长 | v: 输入的向量 | 向量的模长 |
vec3_len_sq | 计算向量模长的平方 | v: 输入的向量 | 向量模长的平方 |
vec3_dist | 计算两个向量之间的距离 | v0, v1: 要计算距离的向量 | 两个向量之间的距离 |
vec3_dist_sq | 计算两个向量之间距离的平方 | v0, v1: 要计算距离的向量 | 两个向量之间距离的平方 |
vec3 | 创建向量结构体 | x, y, z: 向量的分量 | 创建的向量结构体 |
vec3_v | 通过数组创建向量结构体 | v[3]: 包含三个分量的数组 | 创建的向量结构体 |
vec3_zero | 创建零向量 | 无 | 所有分量为0.0的向量 |
vec3_one | 创建全1向量 | 无 | 所有分量为1.0的向量 |
vec3_sign | 计算向量的符号向量 | v: 输入的向量 | 符号向量 |
vec3_add | 向量加法 | v0, v1: 要相加的向量 | 两个向量的和 |
vec3_add_f | 向量与标量加法 | v: 输入的向量, f: 标量值 | 向量与标量的和 |
vec3_sub | 向量减法 | v0, v1: 要相减的向量 | 两个向量的差 |
vec3_sub_f | 向量与标量减法 | v: 输入的向量, f: 标量值 | 向量与标量的差 |
vec3_mul | 向量逐分量乘法 | v0, v1: 要相乘的向量 | 两个向量的逐分量乘积 |
vec3_mul_f | 向量与标量乘法 | v: 输入的向量, f: 标量值 | 向量与标量的乘积 |
vec3_div | 向量逐分量除法 | v0, v1: 要相除的向量 | 两个向量的逐分量商 |
vec3_div_f | 向量与标量除法 | v: 输入的向量, f: 标量值 | 向量与标量的商 |
vec3_snap | 向量逐分量取整 | v0, v1: 要取整的向量 | 逐分量取整后的向量 |
vec3_snap_f | 向量与标量取整 | v: 输入的向量, f: 标量值 | 与标量取整后的向量 |
vec3_wrapping_f | 向量环绕 | v: 输入的向量, f: 环绕值 | 环绕后的向量 |
vec3_neg | 计算向量的负向量 | v: 输入的向量 | 负向量 |
vec3_abs | 计算向量的绝对值向量 | v: 输入的向量 | 绝对值向量 |
vec3_floor | 计算向量的向下取整向量 | v: 输入的向量 | 向下取整向量 |
vec3_ceil | 计算向量的向上取整向量 | v: 输入的向量 | 向上取整向量 |
vec3_round | 计算向量的四舍五入向量 | v: 输入的向量 | 四舍五入向量 |
vec3_trunc | 计算向量的截断向量 | v: 输入的向量 | 截断向量 |
vec3_max | 计算两个向量的逐分量最大值 | v0, v1: 要比较的向量 | 逐分量最大值向量 |
vec3_min | 计算两个向量的逐分量最小值 | v0, v1: 要比较的向量 | 逐分量最小值向量 |
vec3_clamp | 向量钳制 | v: 输入的向量, min: 最小值向量, max: 最大值向量 | 钳制后的向量 |
vec3_clamp_min_abs | 向量最小绝对值钳制 | v: 输入的向量, min_abs: 最小绝对值 | 钳制后的向量 |
vec3_clamp_max_abs | 向量最大绝对值钳制 | v: 输入的向量, max_abs: 最大绝对值 | 钳制后的向量 |
vec3_cross | 计算两个向量的叉积 | v0, v1: 要计算叉积的向量 | 两个向量的叉积 |
vec3_unit | 计算向量的单位向量 | v: 输入的向量 | 单位向量 |
vec3_project | 计算向量在另一个向量上的投影 | v: 输入的向量, onto: 投影目标向量 | 投影向量 |
vec3_slide | 计算向量在平面上的滑动 | v: 输入的向量, normal: 平面法向量 | 滑动向量 |
vec3_reflect | 计算向量在平面上的反射 | v: 输入的向量, normal: 平面法向量 | 反射向量 |
vec3_rotate | 绕轴旋转向量 | v: 输入的向量, axis: 旋转轴, angle: 旋转角度 | 旋转后的向量 |
vec3_lerp | 向量线性插值 | from, to: 起始和结束向量, t: 插值因子 | 插值后的向量 |
vec3_bezier3 | 三次贝塞尔曲线插值 | v0, v1, v2: 控制点, f: 插值因子 | 贝塞尔曲线上的点 |
vec3_bezier4 | 四次贝塞尔曲线插值 | v0, v1, v2, v3: 控制点, f: 插值因子 | 贝塞尔曲线上的点 |
四元数函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
quat_is_zero | 判断四元数是否为零四元数 | q: 要检查的四元数 | 如果所有分量都接近零则返回true |
quat_is_equal | 判断两个四元数是否相等 | q0, q1: 要比较的四元数 | 如果所有分量都接近相等则返回true |
quat_dot | 计算两个四元数的点积 | q0, q1: 要计算点积的四元数 | 两个四元数的点积 |
quat_len | 计算四元数的模长 | q: 输入的四元数 | 四元数的模长 |
quat_len_sq | 计算四元数模长的平方 | q: 输入的四元数 | 四元数模长的平方 |
quat_angle | 计算两个四元数之间的角度 | q0, q1: 要计算角度的四元数 | 两个四元数之间的角度(弧度) |
quat_rotate_vec3 | 使用四元数旋转向量(标准方法) | q: 旋转四元数, v: 要旋转的向量 | 旋转后的向量 |
quat_rotate_vec3_fast | 使用四元数旋转向量(优化方法) | q: 旋转四元数, v: 要旋转的向量 | 旋转后的向量 |
quat_rotate_vec3_components | 使用四元数旋转向量(分量方法) | q: 旋转四元数, v: 要旋转的向量 | 旋转后的向量 |
quat | 创建四元数结构体 | x, y, z, w: 四元数的分量 | 创建的四元数 |
quat_v | 通过v[4]数组对四元数赋值 | v[4]: 输入数组 | 创建的四元数 |
quat_zero | 创建一个零四元数 | 无 | 所有分量为0.0的四元数 |
quat_null | 创建一个单位四元数(无旋转) | 无 | 单位四元数 [0, 0, 0, 1] |
quat_identity | 创建一个单位四元数(无旋转) | 无 | 单位四元数 [0, 0, 0, 1] |
quat_add | 四元数加法 | q0, q1: 要相加的四元数 | 两个四元数的和 |
quat_sub | 四元数减法 | q0, q1: 要相减的四元数 | 两个四元数的差 |
quat_mul | 四元数乘法 | q0, q1: 要相乘的四元数 | 两个四元数的乘积 |
quat_mul_f | 四元数标量乘法 | q: 输入的四元数, f: 标量乘数 | 四元数与标量的乘积 |
quat_div | 四元数除法 | q0, q1: 要相除的四元数 | 四元数除法结果 |
quat_div_f | 四元数标量除法 | q: 输入的四元数, f: 标量除数 | 四元数与标量的除法结果 |
quat_neg | 计算四元数的负四元数 | q: 输入的四元数 | 负四元数 |
quat_conjugate | 计算四元数的共轭 | q: 输入的四元数 | 共轭四元数 |
quat_inverse | 计算四元数的逆 | q: 输入的四元数 | 四元数的逆 |
quat_normalize | 归一化四元数 | q: 输入的四元数 | 归一化后的四元数 |
quat_continuous | 保持新的四元数与旧四元数连续 | q0: 旧四元数, q1: 新四元数 | 保持连续性的新四元数 |
quat_pow | 计算四元数的幂 | q: 输入的四元数, exponent: 指数 | 四元数的幂 |
quat_from_axis_angle | 从轴角创建四元数 | axis: 旋转轴向量, angle: 旋转角度 | 表示旋转的四元数 |
quat_from_vv | 从两个向量创建四元数 | from: 起始向量, to: 目标向量 | 将from旋转到to的四元数 |
quat_lerp | 四元数线性插值 | from, to: 起始和结束四元数, t: 插值因子 | 插值后的四元数 |
quat_slerp | 四元数球面线性插值 | from, to: 起始和结束四元数, t: 插值因子 | 球面插值后的四元数 |
quat_rotation_x | 创建绕X轴旋转的四元数 | angle: 旋转角度 | 绕X轴旋转的四元数 |
quat_rotation_y | 创建绕Y轴旋转的四元数 | angle: 旋转角度 | 绕Y轴旋转的四元数 |
quat_rotation_z | 创建绕Z轴旋转的四元数 | angle: 旋转角度 | 绕Z轴旋转的四元数 |
quat_derivative | 计算四元数对时间的导数 | q: 当前四元数, omega: 角速度向量 | 四元数的导数 |
quat_integrate | 四元数积分 | q: 当前四元数, q_dot: 四元数导数, dt: 时间步长 | 积分后的四元数 |
quat_integrate_w | 使用角速度进行四元数积分 | q: 当前四元数, w: 角速度向量, dt: 时间步长 | 积分后的四元数 |
旋转函数 - 基本旋转操作
| 函数名 | 功能 | 参数 | 返回值 |
|---|
rotation_a_rvs | 计算轴角表示的逆旋转 | a: 输入的轴角表示 | 逆轴角表示 |
rotation_a_rx | 创建绕X轴旋转的轴角表示 | angle: 旋转角度 | 绕X轴旋转的轴角表示 |
rotation_a_ry | 创建绕Y轴旋转的轴角表示 | angle: 旋转角度 | 绕Y轴旋转的轴角表示 |
rotation_a_rz | 创建绕Z轴旋转的轴角表示 | angle: 旋转角度 | 绕Z轴旋转的轴角表示 |
rotation_e_rvs | 计算欧拉角表示的逆旋转 | e: 输入的欧拉角表示 | 逆欧拉角表示 |
rotation_e_rx | 创建绕X轴旋转的欧拉角表示 | angle: 旋转角度 | 绕X轴旋转的欧拉角表示 |
rotation_e_ry | 创建绕Y轴旋转的欧拉角表示 | angle: 旋转角度 | 绕Y轴旋转的欧拉角表示 |
rotation_e_rz | 创建绕Z轴旋转的欧拉角表示 | angle: 旋转角度 | 绕Z轴旋转的欧拉角表示 |
rotation_m_rvs | 计算旋转矩阵的逆旋转 | m: 输入的旋转矩阵 | 逆旋转矩阵 |
rotation_m_rx | 创建绕X轴旋转的旋转矩阵 | angle: 旋转角度 | 绕X轴旋转的旋转矩阵 |
rotation_m_ry | 创建绕Y轴旋转的旋转矩阵 | angle: 旋转角度 | 绕Y轴旋转的旋转矩阵 |
rotation_m_rz | 创建绕Z轴旋转的旋转矩阵 | angle: 旋转角度 | 绕Z轴旋转的旋转矩阵 |
rotation_q_rvs | 计算四元数的逆旋转 | q: 输入的四元数 | 逆四元数 |
rotation_q_rx | 创建绕X轴旋转的四元数 | angle: 旋转角度 | 绕X轴旋转的四元数 |
rotation_q_ry | 创建绕Y轴旋转的四元数 | angle: 旋转角度 | 绕Y轴旋转的四元数 |
rotation_q_rz | 创建绕Z轴旋转的四元数 | angle: 旋转角度 | 绕Z轴旋转的四元数 |
旋转函数 - 旋转转换函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
rotation_e2m_order | 将欧拉旋转角转换为旋转矩阵(指定顺序) | e: 欧拉旋转角, order: 旋转顺序 | 对应的旋转矩阵 |
rotation_m2e_order | 将旋转矩阵转换为欧拉旋转角(指定顺序) | m: 旋转矩阵, order: 旋转顺序 | 对应的欧拉旋转角 |
rotation_e2q_order | 将欧拉旋转角转换为四元数(指定顺序) | e: 欧拉旋转角, order: 旋转顺序 | 对应的四元数 |
rotation_q2e_order | 将四元数转换为欧拉旋转角(指定顺序) | q: 输入的四元数, order: 旋转顺序 | 对应的欧拉旋转角 |
rotation_a2e | 将轴角转换为欧拉旋转角 | a: 输入的轴角表示 | 对应的欧拉旋转角 |
rotation_a2m | 将轴角转换为旋转矩阵 | a: 输入的轴角表示 | 对应的旋转矩阵 |
rotation_a2q | 将轴角转换为四元数 | a: 输入的轴角表示 | 对应的四元数 |
rotation_e2a | 将欧拉旋转角转换为轴角 | e: 输入的欧拉旋转角 | 对应的轴角表示 |
rotation_e2m | 将欧拉旋转角转换为旋转矩阵 | e: 输入的欧拉旋转角 | 对应的旋转矩阵 |
rotation_e2q | 将欧拉旋转角转换为四元数 | e: 输入的欧拉旋转角 | 对应的四元数 |
rotation_m2a | 将旋转矩阵转换为轴角 | m: 输入的旋转矩阵 | 对应的轴角表示 |
rotation_m2e | 将旋转矩阵转换为欧拉旋转角 | m: 输入的旋转矩阵 | 对应的欧拉旋转角 |
rotation_m2q | 将旋转矩阵转换为四元数 | m: 输入的旋转矩阵 | 对应的四元数 |
rotation_q2a | 将四元数转换为轴角 | q: 输入的四元数 | 对应的轴角表示 |
rotation_q2e | 将四元数转换为欧拉旋转角 | q: 输入的四元数 | 对应的欧拉旋转角 |
rotation_q2m | 将四元数转换为旋转矩阵 | q: 输入的四元数 | 对应的旋转矩阵 |
rotation_vv2a | 由两个向量计算旋转轴角 | from: 起始向量, to: 目标向量 | 将from旋转到to所需的轴角 |
rotation_vv2e | 由两个向量计算旋转欧拉角 | from: 起始向量, to: 目标向量 | 将from旋转到to所需的欧拉角 |
rotation_vv2m | 由两个向量计算旋转矩阵 | from: 起始向量, to: 目标向量 | 将from旋转到to所需的旋转矩阵 |
rotation_vv2q | 由两个向量计算旋转四元数 | from: 起始向量, to: 目标向量 | 将from旋转到to所需的四元数 |
rotation_aa2a | 计算两个轴角之间的相对旋转 | from: 起始轴角, to: 目标轴角 | 将from旋转到to所需的轴角 |
rotation_ee2e | 计算两个欧拉角之间的相对旋转 | from: 起始欧拉角, to: 目标欧拉角 | 将from旋转到to所需的欧拉角 |
rotation_mm2m | 计算两个旋转矩阵之间的相对旋转 | from: 起始旋转矩阵, to: 目标旋转矩阵 | 将from旋转到to所需的旋转矩阵 |
rotation_qq2q | 计算两个四元数之间的相对旋转 | from: 起始四元数, to: 目标四元数 | 将from旋转到to所需的四元数 |
旋转函数 - 旋转应用函数
| 函数名 | 功能 | 参数 | 返回值 |
|---|
rotation_aRa | 使用轴角旋转轴角 | ra: 旋转轴角, a: 被旋转的轴角 | 旋转后的轴角 |
rotation_eRa | 使用欧拉角旋转轴角 | re: 旋转欧拉角, a: 被旋转的轴角 | 旋转后的轴角 |
rotation_mRa | 使用旋转矩阵旋转轴角 | rm: 旋转矩阵, a: 被旋转的轴角 | 旋转后的轴角 |
rotation_qRa | 使用四元数旋转轴角 | rq: 旋转四元数, a: 被旋转的轴角 | 旋转后的轴角 |
rotation_aRe | 使用轴角旋转欧拉角 | ra: 旋转轴角, e: 被旋转的欧拉角 | 旋转后的欧拉角 |
rotation_eRe | 使用欧拉角旋转欧拉角 | re: 旋转欧拉角, e: 被旋转的欧拉角 | 旋转后的欧拉角 |
rotation_mRe | 使用旋转矩阵旋转欧拉角 | rm: 旋转矩阵, e: 被旋转的欧拉角 | 旋转后的欧拉角 |
rotation_qRe | 使用四元数旋转欧拉角 | rq: 旋转四元数, e: 被旋转的欧拉角 | 旋转后的欧拉角 |
rotation_aRm | 使用轴角旋转旋转矩阵 | ra: 旋转轴角, m: 被旋转的旋转矩阵 | 旋转后的旋转矩阵 |
rotation_eRm | 使用欧拉角旋转旋转矩阵 | re: 旋转欧拉角, m: 被旋转的旋转矩阵 | 旋转后的旋转矩阵 |
rotation_mRm | 使用旋转矩阵旋转旋转矩阵 | rm: 旋转矩阵, m: 被旋转的旋转矩阵 | 旋转后的旋转矩阵 |
rotation_qRm | 使用四元数旋转旋转矩阵 | rq: 旋转四元数, m: 被旋转的旋转矩阵 | 旋转后的旋转矩阵 |
rotation_aRq | 使用轴角旋转四元数 | ra: 旋转轴角, q: 被旋转的四元数 | 旋转后的四元数 |
rotation_eRq | 使用欧拉角旋转四元数 | re: 旋转欧拉角, q: 被旋转的四元数 | 旋转后的四元数 |
rotation_mRq | 使用旋转矩阵旋转四元数 | rm: 旋转矩阵, q: 被旋转的四元数 | 旋转后的四元数 |
rotation_qRq | 使用四元数旋转四元数 | rq: 旋转四元数, q: 被旋转的四元数 | 旋转后的四元数 |
rotation_aRv | 使用轴角旋转向量 | ra: 旋转轴角, v: 被旋转的向量 | 旋转后的向量 |
rotation_eRv | 使用欧拉角旋转向量 | re: 旋转欧拉角, v: 被旋转的向量 | 旋转后的向量 |
rotation_mRv | 使用旋转矩阵旋转向量 | rm: 旋转矩阵, v: 被旋转的向量 | 旋转后的向量 |
rotation_qRv | 使用四元数旋转向量 | rq: 旋转四元数, v: 被旋转的向量 | 旋转后的向量 |
修改记录
| 修改日期 | 修改人 | 版本号 | 修改内容 |
|---|
| 2025.09.01 | scilogyhunter | V0.1.0 | 初始版本创建 |
| 2025.11.18 | scilogyhunter | V0.1.1 | 完善注释,使用doxygen格式 |
| 2025.12.28 | scilogyhunter | V0.1.2 | 补充API,调整参数顺序,去掉旋转向量,优化测试程序 |
所有评论(0)