我在下面有一个模板和两个 Vector 类,一个疯狂,一个理智。该模板实现了一个简单的在编译时固定的值数组。它专为子类化而设计,并使用受保护的数组变量来避免您必须跳过箍来访问数组。(有些人可能不喜欢这样的设计。我说,如果你的子类调用你的重载运算符,耦合可能是个好主意。)
这个疯狂的类允许你拥有名为 x、y、z 的成员变量,它就像一个用于调用 glGetFloatV 的数组。理智的只有访问函数 x()、y()、z() 并且仍然可以与 glGetFloatV 一起使用。您可以使用任一类作为您可能传递给 OpenGL 库的其他矢量对象的基础。尽管下面的类是特定于点的,但显然您可以进行搜索/替换以将它们变成 rgb 颜色类。
疯狂的类是疯狂的,因为语法糖 vec.x 而不是 vec.x() 的成本是 3 个参考变量。在大型应用程序中,这可能会占用大量空间。使用更简单的健全版本。
template <typename T, int N>
class FixedVector {
protected:
T arr[N];
public:
FixedVector();
FixedVector(const T* a) {
for (int i = 0; i < N; ++i) {
arr[i] = a[i];
}
}
FixedVector(const T& other) {
for (int i = 0; i < N; ++i) {
arr[i] = other.arr[i];
}
}
FixedVector& operator=(const T& other) {
for (int i = 0; i < N; ++i) {
arr[i] = other.arr[i];
}
return *this;
}
T* operator&() { return arr; }
const T* operator&() const { return arr; }
T& operator[](int ofs) {
assert(ofs >= 0 && ofs < N);
return arr[ofs];
}
const T& operator[](int ofs) const {
assert(ofs >= 0 && ofs < N);
return arr[ofs];
}
};
class CrazyPoint : public FixedVector<float, 3> {
public:
float &x, &y, &z;
CrazyPoint()
: x(arr[0]), y(arr[1]), z(arr[2])
{ arr[0] = arr[1] = arr[2] = 0.0; }
CrazyPoint(const float* a)
: x(arr[0]), y(arr[1]), z(arr[2])
{
arr[0] = a[0];
arr[1] = a[1];
arr[2] = a[2];
}
CrazyPoint(float a, float b, float c)
: x(a), y(b), z(c)
{
arr[0] = a;
arr[1] = b;
arr[2] = c;
}
};
class SanePoint : public FixedVector<float, 3> {
public:
float& x() { return arr[0]; }
float& y() { return arr[1]; }
float& z() { return arr[2]; }
SanePoint() { arr[0] = arr[1] = arr[2] = 0.0; }
SanePoint(float a, float b, float c)
{
arr[0] = a;
arr[1] = b;
arr[2] = c;
}
};
// usage
SanePoint normal;
glGetFloatV(GL_CURRENT_NORMAL, &normal);