cglm 0.7.9

cglm 0.7.9

Recep Aslantasai mac 维护。



cglm 0.7.9

  • 作者:Recep Aslantas
  • By

GitHub 仓库🎥

Build Status Build status Documentation Status Coverage Status codecov Codacy Badge Backers on Open Collective Sponsors on Open Collective

OpenGL 数学 (glm) 的 C 语言版本

几乎所有的函数(内联版本)和参数都在对应的头文件中进行了文档描述。
完整文档:http://cglm.readthedocs.io

关于先前版本的说明

  • 对于先前版本,_dup(复制)已被更名为_copy。例如 glm_vec_dup -> glm_vec3_copy
  • 移除与 OpenGL 相关的函数,以使此库与平台和无第三方依赖
  • 确保您有最新版本,并随时报告错误或问题
  • [错误修复] 欧拉角(euler angles)的实现顺序错误(外部的),已修复,现在是内部的。请确保您有最新版本
  • [主要变更] 从 v0.4.0 开始,四元数存储为 [x, y, z, w],在 v0.3.5 和更早的版本中是 [w, x, y, z]
  • [API 重命名] 从 v0.4.5 开始,glm_simd 函数更名为 glmm_
  • [新增选项] 从 v0.4.5 开始,您可以禁用对齐要求,有关文档中的选项检查。
  • [主要变更] 从 v0.5.0 开始,vec3 函数使用 glm_vec3_ 命名空间,在 v0.5.0 之前是 glm_vec_
  • [主要变更] 从 v0.5.1 开始,从 vec3mat3 类型中移除了内置对齐
  • [主要变更] 从 v0.7.3 开始,在发布/生产模式下禁用内联打印函数以消除打印成本(请参阅文档中的选项)。如果需要,您还可以禁用颜色(请参阅文档)

对于 C++ 开发者的说明

如果你还不熟悉原始的 GLM 库,你还可能想看看: https://github.com/g-truc/glm

新手的注意事项(重要)

  • vec4mat4 变量必须对齐。(稍后将提供非对齐版本)
  • in[in, out] 参数必须初始化(请务必如此)。但是 [out] 参数不必初始化,初始化出参也是多余的
  • 如果你不想使用带有 glmc_ 前缀的预编译版本,所有函数都是内联的,你可以忽略构建过程。只需包含头文件。
  • 如果你的调试器带你进入了 cglm 头文件,请确保你不是在尝试复制 vec4 到 vec3 或者处理对齐问题...
  • 欢迎!

经验丰富的开发者的说明

  • 由于我在项目中测试了这个库,有时会出错;如果有多个开发者和他们的项目或知识找到这些错误并进行改进,将会更容易。如果你怀疑有什么问题,可以考虑进行一些测试,任何反馈、贡献和错误报告都非常欢迎。

分配?

cglm 不会在堆上进行内存分配。所以它不提供任何分配器。如果你传递了内存位置的指针,你还需要为 out 参数分配内存。别忘了,vec4(以及quat/ versor)和 mat4 必须对齐(16 字节),因为 cglm 如果可用,会使用SIMD指令来优化大多数操作。

返回向量或矩阵...

cglm 支持同时使用 数组API结构体API,因此如果您使用结构体API(glms_)的话,您可以返回结构体。

其他API如Vulkan、Metal、Dx?

目前,cglm 使用默认裁剪空间配置(-1,1)用于相机函数(透视、提取角...),未来将支持其他裁剪空间配置。


像一些其他图形库(尤其是OpenGL)一样,此库使用列主序布局以在内存中保持矩阵。
 
未来库可能会支持使用行主序布局的选项,目前如果您需要行主序布局,您需要将其转置。

功能

  • 数组API和结构体API,你可以使用数组或结构体。
  • 通用的矩阵操作(mat4,mat3)
  • 链式矩阵乘法(仅限平方)
  • 通用的向量操作(叉积、点积、旋转、投影、角度...)
  • 仿射变换
  • 矩阵分解(提取旋转、缩放因子)
  • 优化的仿射变换矩阵(乘法、刚体逆变换)
  • 相机(lookat)
  • 投影(正交、透视)
  • 四元数
  • 欧拉角/偏航-俯仰-翻滚到矩阵
  • 提取欧拉角
  • 内联或预编译函数调用
  • 视锥体(提取视锥体平面、角...)
  • 包围盒(在视锥体中(裁剪)、裁剪、合并...)
  • 包围球
  • 投影、反投影
  • 缓动函数
  • 曲线
  • 曲线插值助手(SMC、deCasteljau...)
  • 将cglm类型转换为Apple的simd库的助手,以便在Metal GL中使用cglm类型而不在两侧打包它们
  • 光线追踪助手
  • 等等...

您有两个选项来调用函数/操作:内联或库调用(链接)。几乎所有函数都标记为内联(always_inline),所以编译器可能会内联。要调用预编译版本,请使用 glmc_(c代表'call')而不是 glm_

  #include <cglm/cglm.h>   /* for inline */
  #include <cglm/call.h>   /* for library call (this also includes cglm.h) */

  mat4 rot, trans, rt;
  /* ... */
  glm_mul(trans, rot, rt);  /* inline */
  glmc_mul(trans, rot, rt); /* call from library */

大多数数学函数都使用SSE2进行手动优化(如果可用),如果不行?别担心,所有操作都有非SSE版本。

您可以将矩阵和向量作为数组传递给函数,而不是获取地址。

  mat4 m = {
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
  };

  glm_translate(m, (vec3){1.0f, 0.0f, 0.0f});

该库包含通用的mat4乘法和逆函数,并且包含这些函数一些特殊形式(优化)用于仿射变换矩阵。如果您想乘以两个仿射变换矩阵,可以使用glm_mul代替glm_mat4_mul,以及使用glm_inv_tr (ROT + TR)代替glm_mat4_inv。

/* multiplication */
mat4 modelMat;
glm_mul(T, R, modelMat);

/* othonormal rot + tr matrix inverse (rigid-body) */
glm_inv_tr(modelMat);

结构体API

结构体API这样工作,注意类型后有`s`后缀,函数前有`glms_`前缀,常量前有`GLMS_`前缀。

#include <cglm/struct.h>

mat4s mat = GLMS_MAT4_IDENTITY_INIT;
mat4s inv = glms_mat4_inv(mat);

结构体函数通常使用作为参数并返回结果,而不是使用指针并将输出参数写回。这意味着您的参数通常是const,如果您喜欢的话。

使用的类型实际上是允许以多种方式访问相同数据的联合。其中一种方式涉及匿名结构,自C11以来可用。MSVC还支持早期C版本的匿名结构,GCC/Clang在启用-fms-extensions的情况下也支持。要显式启用这些匿名结构,请将CGLM_USE_ANONYMOUS_STRUCT定义为1,要禁用它们,请将其定义为0。为了向后兼容,您还可以定义CGLM_NO_ANONYMOUS_STRUCT(值无关紧要)以禁用它们。如果没有显式指定,cglm将根据您的编译器和使用的C版本进行最佳猜测。

构建

CMake(所有平台)

$ mkdir build
$ cd build
$ cmake .. # [Optional] -DCGLM_SHARED=ON
$ make
$ sudo make install # [Optional]
CMake选项(带默认值)
option(CGLM_SHARED "Shared build" ON)
option(CGLM_STATIC "Static build" OFF)
option(CGLM_USE_C99 "" OFF) # C11 
option(CGLM_USE_TEST "Enable Tests" OFF) # for make check - make test

与您的CMake项目一起使用

  • 示例
cmake_minimum_required(VERSION 3.8.2)

project(<Your Project Name>)

add_executable(${PROJECT_NAME} src/main.c)
target_link_libraries(${LIBRARY_NAME} PRIVATE
  cglm)

add_subdirectory(external/cglm/)

# or you can use find_package to configure cglm

Meson(所有平台)

$ meson build # [Optional] --default-library=static
$ cd build
$ ninja
$ sudo ninja install # [Optional]
带有默认值的Meson选项
c_std=c11
buildtype=release
default_library=shared
enable_tests=false # to run tests: ninja test

与您的Meson项目一起使用

  • 示例
# Clone cglm or create a cglm.wrap under <source_root>/subprojects
project('name', 'c')

cglm_dep = dependency('cglm', fallback : 'cglm', 'cglm_dep')

executable('exe', 'src/main.c', dependencies : cglm_dep)

Swift(Swift包管理器)

目前只支持默认构建选项。将 cglm 依赖项添加到您的项目中

...
Package( 
  ...
  dependencies: [
    ...
    .package(url: "https://github.com/recp/cglm", .branch("master")),
  ]
  ...
)

现在将 cgml 添加为目标依赖项。产品选择包括

  • cglm 用于库的内联版本,只能进行静态链接
  • cglmc 用于库的编译版本,无链接限制
...
.target(
  ...
  dependencies: [
    ...
    .product(name: "cglm", package: "cglm"),
  ]
  ...
)
...

Unix(Autotools)

$ sh autogen.sh
$ ./configure
$ make
$ make check # [Optional]
$ [sudo] make install # [Optional]

这也会安装pkg-config文件,因此您可以使用 pkg-config --cflags cglmpkg-config --libs cglm 来检索编译器和链接器标志。

文件将被安装到指定的前缀下(通常在Linux系统中默认为/usr/local),但你的pkg-config可能没有配置实际上检查这里的设置。你可以通过运行pkg-config --variable pc_path pkg-config来找出其查找位置,并通过./configure --with-pkgconfigdir=/your/path更改文件安装的路径。或者,你可以添加前缀路径到你的PKG_CONFIG_PATH环境变量。

Windows (MSBuild)

有关Windows的构建文件和项目文件位于win文件夹中,确保你处于cglm/win文件夹内。已启用代码分析,所以构建可能需要一些时间。

$ cd win
$ .\build.bat

如果msbuild不起作用(因为多版本VS),那么尝试使用devenv进行构建。

$ devenv cglm.sln /Build Release

在Windows上运行测试

你可以在相同的Visual Studio解决方案文件中看到测试项目。只需运行该项目即可运行测试。

构建文档

首先你需要安装Sphinx:https://sphinx-doc.cn/en/master/usage/installation.html然后

$ cd docs
$ sphinx-build source build

它将编译文档到构建文件夹中,你可以运行该文件夹中的index.html。

如何使用

如果你想要使用函数的内联版本,那么包含主头文件

#include <cglm/cglm.h>

头文件将包含所有头文件。然后调用你想要的函数,例如沿着轴线旋转矢量

glm_vec3_rotate(v1, glm_rad(45), (vec3){1.0f, 0.0f, 0.0f});

一些函数是重载的,例如你可以归一化矢量

glm_vec3_normalize(vec);

这将归一化vec并将归一化的矢量存储到vec中,但如果你要将归一化的矢量存储到另一个矢量中,这样做

glm_vec3_normalize_to(vec, result);

像这样的函数,你可能看到_to后缀,这些函数将结果存储到另一个变量中,并节省临时内存

要调用预编译版本,包含带c后缀的头文件,c代表调用。预编译版本不过是包装器。

#include <cglm/call.h>

这个头文件将包含所有带c后缀的头文件。你需要用带c后缀的方式调用函数

glmc_vec3_normalize(vec);

函数用法和参数在相关头文件中进行了文档说明。在某些例子中,您可能看到相同的参数被传递了两次,如下所示

glm_mat4_mul(m1, m2, m1);

/* or */
glm_mat4_mul(m1, m1, m1);

前两个参数是 [in] 参数,最后一个参数是 [out] 参数。将 m1m2 相乘后,结果存储在 m1 中。这就是为什么我们要传递两次 m1。您也可以将结果存储在不同的矩阵中,这只是一个示例。

示例:计算 MVP 矩阵

选项 1

mat4 proj, view, model, mvp;

/* init proj, view and model ... */

glm_mat4_mul(proj, view, viewProj);
glm_mat4_mul(viewProj, model, mvp);

选项 2

mat4 proj, view, model, mvp;

/* init proj, view and model ... */

glm_mat4_mulN((mat4 *[]){&proj, &view, &model}, 3, mvp);

如何发送矩阵到 OpenGL

mat4 是 vec4 的数组,vec4 是浮点数的数组。 glUniformMatrix4fv 函数接受 float* 作为 value(最后一个参数),所以您可以将其转换为 float*,或者可以将矩阵的第一个列作为矩阵内存的起始点。

选项 1:发送第一列

glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0]);

/* array of matrices */
glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0][0]);

选项 2:将矩阵转换为指针类型(也适用于多维数组)

glUniformMatrix4fv(location, 1, GL_FALSE, (float *)matrix);

您可以用相同的方式将矩阵传递给其他 API,例如 Vulkan、DX...

备注

  • 此库仅使用浮点类型,尚不支持整数、双精度等。
  • 如果头文件与您的编译器或 IDE 不正常工作,请提交问题,因为我使用 GCC 和 clang 进行测试,有时可能是 MSVC

待办事项

  • 单元测试(进行中)
  • 比较 cglm 与 glm 结果的单元测试
  • 添加版本信息
  • 未对齐操作(例如 glm_umat4_mul
  • 补充文档
  • ARM Neon 架构(进行中)

贡献者

本项目的存在归功于所有贡献者。[贡献]

赞助者

感谢所有的赞助者!🙏[成为赞助者]

赞助商

通过成为赞助商支持本项目。您的标志将在这里显示,并带有指向您网站的链接。[成为赞助商]

许可

MIT。请查看LICENSE文件