2个版本

0.1.1 2021年2月19日
0.1.0 2021年2月19日
0.0.0 2021年2月14日

#1731 in 数学

自定义许可

28KB
470

gfxmath-vec4

一个简单的3D数学库,用于计算三维向量。

使用方法

Vec4

Vec4使用{ x, y, z }坐标系,尾部有w。我们可以通过调用其成员来获取每个轴的系数。

Vec4的结构如下

pub struct Vec4<T> {
    pub x: T,
    pub y: T,
    pub z: T,
    pub w: T
}

根据上下文,Vec4可以用来表示不同类型的数据。在图形计算中,通常使用Vec4来表示点和向量,使用w来区分它们。

例如,当w等于0.0时,它会被视为一个向量,而非零值则被视为3D空间中的一个点。有时,w也可以用来表示向量或点的缩放因子。

在颜色的例子中,我们可以使用{ x, y, z, w }来表示(红,绿,蓝,alpha)。

创建Vec4对象可以通过多种方式完成。

use gfxmath_vec4::Vec4;

// Standard construction
let v = Vec4 { x: 3.0, y: 1.0, z: 0.5, w: 4.2 };

// Using `new` function
let v = Vec4::new(3.0, 1.0, 0.5, 4.2);

// Using tuples
let v: Vec4<f32> = (3.0, 4.0, 9.0, 4.2).into();

// Using macros
use gfxmath_vec4::vec4;
let v = vec4!(3.0, 4.0, 9.0, 4.2);

assert_eq!(3.0, v.x);
assert_eq!(1.0, v.y);
assert_eq!(0.5, v.z);
assert_eq!(4.2, v.w);

运算符

Vec3实现了常见的数学运算符。

  • + , +=
  • - , -=
  • * , *=
  • / , /=
// Reminder: Rust automatically infers floats to `f64` and integers to `i64`.

let v1 = Vec4::new(3.0, 9.0, 2.5, 1.0);
let v2 = Vec4::new(4.0, 5.0, 3.0, 0.0);

let res = v1 + v2;

assert_eq!( 7.0, res.x);
assert_eq!(14.0, res.y);
assert_eq!( 5.5, res.z);
assert_eq!( 1.0, res.w);

叉积

叉积返回一个w值为零的3D向量。

use gfxmath_vec4::ops::Cross;
use gfxmath_vec4::Vec4;

let a = Vec4::new(1.0, 3.0, 2.5, 9.0);
let b = Vec4::all(2.0);

let res = a.cross(b);

assert_eq!( 1.0, res.x);
assert_eq!( 3.0, res.y);
assert_eq!(-4.0, res.z);
assert_eq!( 0.0, res.w);

点积

Vec4的点积仅计算向量的(x,y,z)分量的点积。

use gfxmath_vec4::{Vec4, ops::Dot};
 
let a = Vec4::new(3.0, 4.0, 5.0, 3.0);
let b = Vec4::new(2.0, 1.0, 3.0, 9.0);
 
let res = a.dot(b);
 
assert_eq!(25.0, res);

归一化

我们可以使用来自gfxmath_vec4::ops::Normnorm来归一化向量。

由于norm是表示向量长度的单词,这可能会在将来发生变化。Norm被选择以保持简洁,因此可能对一些人来说有些令人困惑。

use gfxmath_vec4::ops::Norm;
use gfxmath_vec4::Vec4;

let a = Vec4::<f32>::new(3.0, 4.0, 0.0, 0.0);
let an = a.norm().unwrap();

assert_eq!(3.0/5.0, an.x);
assert_eq!(4.0/5.0, an.y);
assert_eq!(0.0, an.z);
assert_eq!(0.0, an.w); // this should always be zero so that this object is represented as a vector

已知限制

左手原语

有一个需要注意的是,当操作符的左侧是原始类型时,其支持是有限的。这是由于对特质的实现存在限制。在 Rust 语法中(由于尾随的 T),以下代码是不合法的:impl <T> Add<Vec3<T>> for T,因为非局部特质的实现必须针对已知类型。由于 Add 来自 core 包,而 T(要实现的类型)并未从本地特质派生,因此这是不可能的。

在撰写本文时,适用于常见操作符左侧原始类型的类型包括 f32f64i32i64

// Works
let lhs: f32 = 4.0;
let rhs = Vec4::<f32>::new(3.0, 4.0, 2.5, 3.0);
let res = lhs + rhs;

// NOT SUPPORTED!!
let lhs: u32 = 4;
let rhs = Vec4::<u32>::new(3, 4, 2, 3);
let res = lhs + rhs;

哈希实现

目前,以下类型的 Hash 实现是有限的:

  • f32
  • f64
  • i32
  • i64
  • u32
  • u64

依赖项

~1.5MB
~35K SLoC