EGE专栏:EGE专栏
一、向量计算
EGE提供了一个用于三维向量计算的 VECTOR3D 类,可以简单地进行向量加减、点乘、叉乘、求向量之间的夹角、求向量长度、向量绕轴旋转等计算操作,相关资料请查阅官方文档。
下面是 VERTOR3D 类的声明(对比头文件内容有区别,移除了函数具体的定义,只对功能进行说明):
// 三维向量,在右手坐标系下计算
struct VECTOR3D;
void EGEAPI rotate_point3d_x(VECTOR3D * pt, float r); //三维坐标 pt 绕 x 轴旋转 r 弧度
void EGEAPI rotate_point3d_y(VECTOR3D * pt, float r); //三维坐标 pt 绕 y 轴旋转 r 弧度
void EGEAPI rotate_point3d_z(VECTOR3D * pt, float r); //三维坐标 pt 绕 z 轴旋转 r 弧度
//三维向量
struct VECTOR3D {
float x, y, z;
//默认构造函数,向量{0, 0, 0}
VECTOR3D();
//构造函数,向量{x, y, 0}
VECTOR3D(float _x, float _y);
//构造函数,向量 {x, y, z}
VECTOR3D(float _x, float _y, float _z);
// 赋值运算符
VECTOR3D& operator = (const VECTOR3D& _fp);
//向量相加
VECTOR3D& operator += (const VECTOR3D& _fp);
VECTOR3D operator + (const VECTOR3D& _fp) const;
//向量相减
VECTOR3D& operator -= (const VECTOR3D& _fp);
VECTOR3D operator - (const VECTOR3D& _fp) const;
//向量乘以标量
VECTOR3D& operator *= (float f); //缩放
VECTOR3D operator * (float f) const; //缩放
//向量点乘
float operator * (const VECTOR3D& _fp) const; //点乘
//向量叉乘
VECTOR3D operator & (const VECTOR3D& _fp) const;
VECTOR3D& operator &= (const VECTOR3D& _fp);
//向量模
float GetModule() const;
//向量模的平方
float GetSqrModule() const;
//转为模长为m的同向向量
VECTOR3D& SetModule(float m);
// 绕向量 v {x, y, z} 旋转 rad 弧度
VECTOR3D& Rotate(float rad, const VECTOR3D& v);
VECTOR3D& Rotate(float rad, float x, float y, float z);
绕由s 叉乘 e得到的与 垂直于 s 和 e 的向量旋转,旋转的弧度与 s 旋转至 e 的弧度一致。
VECTOR3D& Rotate(const VECTOR3D& e, const VECTOR3D& s = VECTOR3D(0.0f, 0.0f, 1.0f));
//返回 s 与 e 的夹角大小(以弧度为单位)
static float GetAngel(const VECTOR3D& e, const VECTOR3D& s = VECTOR3D(0.0f, 0.0f, 1.0f));
};
二、随机函数
C标准库 <stdlib.h> 中已经有了 rand() 来生成随机数,为什么 EGE 中还额外增加生成随机数的函数呢?
这时因为C标准库中的实现,生成的随机数一般是16位无符号整数,取值范围是 0 ~ 65535,精度稍低,只能满足一般的要求。所以 EGE 增加了可以生成 32位随机整数的函数。
1. 随机数列初始化
使用前必须先调用下面的函数一次, 否则得到的将是固定的序列。不调用的话一般用来调试,因为都是同一个随机序列,可以用来分析不同的结果。
void randomize();
2. 生成随机数:random()
调用一次 randomize() 即可确定一个随机数列,后面就可以不断地使用 random(n) 来生成一个 0 0 0 到 n n n 范围内的随机数(不包含 n n n)。
//生成一个 0 到 n 范围内的随机数
unsigned int random(unsigned int n);
如果参数 n 为0 ,那么随机生成一个32位整数(0 ~ 0xFFFFFFFF)。
3. 生成范围内的随机整数:
如果是想生成一个
[
m
i
n
,
m
a
x
)
\left[ min, max \right)
[min,max)范围内的随机值,那么可以先生成
[
0
,
m
a
x
−
m
i
n
)
\left[ 0, max - min \right)
[0,max−min) 范围内的随机数,然后将值加上最小值
m
i
n
min
min,即可想要的值。
考虑到
m
i
n
⩾
m
a
x
min \geqslant max
min⩾max 这种不合法的情况,范围内没有任何元素,但又必须返回一个值,所以可以返回一个原本不可能出现的特殊值 INT_MAX(即 int 类型的最大值)来表示这种无效的情况。这样可以通过返回值是否等于 INT_MAX 来判断参数的有效性。同时,这在参数有效时并不会对结果有影响。
因为范围 [ m i n , m a x ) \left[ min, max \right) [min,max) 是左闭右开, m a x max max 不包括在内,因此不可能出现 int 的最大值。
实现如下:
#include <limits.h>
// 返回在[min, max)范围内的一个随机整数。特殊情况:当 min <= max时返回 INT_MAX
int randomValue(int min, int max)
{
if (min >= max)
return INT_MAX;
else
return random(max - min) + min;
}
如果是想从
[
m
i
n
,
m
a
x
)
\left[ min, max \right)
[min,max)范围内一个以
m
i
n
min
min 起始,间隔为
d
d
d 的等差数列中随机取一个值,那么可以先求出这个范围内等差数列元素的个数 num,再使用 random(num)
生成一个 [0, num) 范围内的随机数 r,最后通过公式 r * d + min 就可以对应到的数列中的相应元素。
实现如下:
// 返回在[min, max)范围内以interval为差的等差序列中的一个随机元素(特殊值:当 min <= max时返回 INT_MAX)
int randomValue(int min, int max, int interval)
{
//空集,返回无效值 INT_MAX
if (min >= max)
return INT_MAX;
//差值为0或负时,范围内的数列只有一个元素min
if (interval <= 0)
return min;
//这里利用了向上取整的公式: (x + (d - 1)) / d来处理,求元素个数num
int num =((max - min) + (interval - 1)) / interval;
return random(num) * interval + min;
}
例如,想要在10~100范围内的偶数(包括10 和 100)中随机取出一个值,那么可以得到等差数列的范围是 [10, 101), 差为 2,按如下调用即可:
randomValue(10, 101, 2);
4. 生成0.0~1.0之间的随机浮点数
生成 0.0 ~ 1.0 范围内的随机数(0.0取到,1.0取不到)是使用 randomf() 函数,函数声明如下:
double randomf();
如果想要扩大到另一个范围,可以将随机数乘以这个范围大小,再加上最小值即可。如生成10.0 到 100.0之间的小数(不包括100), 范围大小 = 最大值 - 最小值= 90.0, 最小值min = 10.0,可以得到:
double min = 10.0, max = 100.0;
// 取[min, max)范围内的随机值
double r = randomf() * (max - min) + min;
EGE专栏:EGE专栏