eigen库安装_开源!C++ 数学操作库 UGM

点击上方“小白学视觉”,选择“星标”公众号

重磅干货,第一时间送达
f5e737395523c0860a3e66e356692f74.png

https://zhuanlan.zhihu.com/p/131145847

本文已由原作者授权,不得擅自二次转载

UGM

Ubpa Graphics Mathematics,Ubpa 图形数学库
名字取自 GLM,OpenGL Mathematics
该处“图形”概念有点大,主要面向渲染,不同于“图形学”

特点

  • 着重“正确”的代数概念(环、线性、度量、赋范、内积、欧式空间、仿射空间等)

  • 面向对象(所有方法都是类方法)

  • 只有头文件 head-only

  • 高性能:SIMD 加速,各算法最优化

  • 利用单继承化优化代码结构(不使用恶心的宏)

  • 提供 natvis 优化 debug 信息

  • ...

0. 前言

项目地址

https://github.com/Ubpa/UGM

直接把 glm,Eigen 等扔掉

目录

  1. 简介

  2. 示例

  3. 安装

  4. 设计思路

  5. 接口

  6. SIMD

  7. Natvis

1. 简介

UGM 是着重于代数概念的数学库,区分向量法向颜色等,从而尽可能地避免了错误的计算。

常用的数学库(如 Eigen,glm)只提供 vec 类,并使其能做各种运算(如 +-*/ 等),但从代数方面考虑,这并不合理。

示例
- 点与点之间不能相加减
- 颜色与点之间没有关系
- 变换矩阵(4x4)与法向的乘积不同于一般向量
- 在考虑齐次坐标时变换矩阵(4x4)与向量和点的乘积不同
- ...

我们通过提供 pointvecnormalrgb 等来区分不同的代数概念,并仅让他们支持合理的操作,这样就能在编译期就发现各种代数方面的错误,另外还能减轻心智负担(根据类型执行不同的操作)。

此外,我们还通过单继承的技术实现了极佳的代码编写,特点如下

  • 复用函数实现(不同于 c++20 的 concept 或者接口,他们只是对类支持的“操作”进行了约束)

  • 空基类优化

  • ...

2. 示例

b5c4b7ddac22ee6f9f73535afa4caa71.png

3. 安装

3.1 环境

  • Win10

  • Git

  • VS 2019

  • CMake-GUI 3.16.3 及以上

  • 支持 SIMD 扩展指令集 SSE 4.1

其他环境自行测试,如成功请告知

3.2 步骤

详细参考项目 README.md

3.3 使用

1d3693b9fddd61bc17f2628c83cb7915.png
963e549e9772055f9736f031c0f179e2.png

4. 设计思路

为了更好地使用该数学库,我们很有必要先了解下该库的设计思路。

4.1 代数概念

该库着重于“正确”的代数概念,使用者可能对这方面并不了解,但只要知道基础的线性代数知识即可,然后遇到不了解的查查 wiki 即可。

下边我简单介绍下该库涉及的主要代数概念。

  • 加法 IAdd:相同元素之间的运算,具有交换性(a+b==b+a)和可逆性(a+(-a)=0)

  • 乘法 IMul:相同元素之间的运算,具有可逆性(a*(1/a)=1),不一定具备交换性(a*b==b*a)。

  • 数乘 IScalarMul:类与标量(如 float)之间的运算,具有交换性。

  • 线性 ILinear:加法 + 数乘,该空间中的元素称为向量

  • 环 IRing:加法 + 乘法

  • 度量 IMetric:也叫距离

  • 赋范 INorm:满足非负齐次三角不等式的向量 => 标量的函数,一般也叫大小 / 长度,可自然诱导出度量(distance(a,b) == (a-b).norm())

  • 内积 IInnerProduct:线性空间中的正定非退化共轭双线性的向量 x 向量 => 标量的函数,可自然诱导出范数(sqrt(dot(x, x)) == norm)

  • 仿射空间 IAffine:具有位置概念的空间,该空间中的元素称为点,会对应一个线性空间,两空间之间的元素有关联,如 point-point => vector,point+vector => point

4.2 底层存储类型

  • 数组 IArray:有序的元素序列,这将是我们各种类的基类,一般是 std::array,其中 T 可以是 float,int,也可以是 point,vec

  • 矩阵IMatrix:一维数组的数组

由于底层存储类型不同,上述代数概念的具体实现有所不同(抽象 => 具体),并引申出新的代数概念

4.2.1 数组

底层存储类型为数组时,则可引申出如下代数概念

  • 欧式(向量)空间 IEuclideanV:线性空间 + 内积(dot(a,b) == a.x*b.x + a.y*b.y + a.z*b.z)

  • 欧式仿射空间 IEuclideanA:欧式(向量)空间对应的仿射空间

  • 逐元素乘 IArrayHadamardProduct:a*b=(a.x*b.x, a.y*b.y, a.z*b.z)

上述各种概念在具体为数组时会有对应的实现,如

860510eaa86ef351c2fa4dc1fd92abfd.png

4.2.2 矩阵

由于该库用于离线渲染,实时渲染,游戏等,基本只要用 float4,因此也只需 3x3 和 4x4 的矩阵,因此该库也限制为只支持 3x3 和 4x4 的矩阵(并特化矩阵的乘法与逆的实现,如循环展开,simd 加速,以提高性能)。

大型矩阵的支持一般需要用线性代数库,如 Eigen 等。

底层通过一维数组的数组来实现,右乘,列优先,同于 OpenGL 与 DX(右乘+列优先的方案十分适合于 SIMD,同理左乘+行优先也如此)。

4.3 类

通过组合多个代数概念并加上具体类型支持的操作,可以轻松得到各种各样的代数类。他们满足不同的操作,极大地帮助使用者避免错误。

目前各种组合(主要部分)如下

03ca701cf95cf126030ec5207bc25335.png

图中含有的类有

  • 向量 vec

  • 法向 normal:本质是二重向量 bivector(wiki, stackoverflow)

  • 点 point

  • 四元数 quat:限制为单位四元数,用于表示旋转

  • 矩阵 mat

  • 变换 transform:可表示仿射变换(平移,旋转,缩放)和射影变换(正交投影,透视投影)

  • 颜色 rgb

  • 缩放 scale

该库还含有类

  • 值 val:加法 + 数乘 + 逐元素乘

  • 欧拉角 euler:roll -> pitch -> yaw,同于 Unity3D

  • 透明颜色 rgba

  • 表面向量 svec:切空间的单位向量,上方向为 z 轴

  • 齐次向量 hvec

  • 包围盒 bbox:axis-aligned bounding box (AABB)

  • 三角形 triangle

  • 直线 line

  • 射线 ray

5. 接口

类由多个代数概念组合而成,所以关键在于把握代数概念的接口,各代数概念位于 :

https://github.com/Ubpa/UGM/tree/master/include/UGM/Interfaces/

所有接口都是类方法,方便使用,大部分情况下都可以利用 IDE 的代码提示功能(如 VS2019 的 intellisense)来查询接口。

此外还提供了图形学常见函数 / 算法,如相交(位于 lineray 内)、采样、材质 等。

6. SIMD

该库支持 SIMD,只要求支持 SSE 指令,使用了 xsimd 作为 SSE 指令的装饰类(wrapper),但大部分情况都直接使用 SSE 指令,并通过检阅汇编代码的指令数来优化与判断加速比。

加速的类为 float4,包括 vecf4pointf4 等。

注意 float3 并没有 SIMD 加速,这是为了保持 sizeof(float3)==3*sizeof(float),部分数学库通过使用含 __m128 的 float3 来实现 SIMD 加速,但这样 sizeof(float3)==4*sizeof(float)。目前可以通过显式将 float3 转成 float4 来获取加速效果。

加速部分包括

  • +-*/ ...

  • min/max/min_component/max_component/abs/sin/cos/...

  • transform * float4/bbox/transform

  • transform inverse

  • ray 和 sphere/triangle/bbox 的相交

  • float3 的 dot/cross(需要扩展成 float4 并使用 float4::dot3 和 float4::cross3)

7. Natvis

泛型编程在 debug 时会引入大量的单继承,该库使用了单继承化技术,单继承深度也很大,导致在 IDE 中查看类成员变量会很麻烦。

c35ac82f34933aa98ce60d2d3a24c10d.png

我们可使用 VS2019 的 natvis 功能来实现定制的视图

26aca935a174481587c52353926afbfd.png

当使用 find_package(UGM REQUIRED) 时,会自动给解决方案添加一个项目,包含 UGM_.natvis,从而使得其他项目都可以支持 natvis(VS2019 支持多种方式引入 natvis,但这是目前我能想到的最合适的方式)。

451dff22ad7840b80987824b988e650f.png

感谢大家的阅读,最后再重复贴一下项目地址

https://github.com/Ubpa/UGM

e9f7e70dff827d35d8e53ba514454cc3.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值