halflife-unified-sdk
halflife-unified-sdk copied to clipboard
Overhaul math related code (Vector/Matrix).
Vector class works in the same way as Vector2D but with an extra dimension. In the event it's possible, I propose to define a single template class for Vector :
template<size_t N>
class VectorT
{
public:
...
// Access components by index.
inline vec_t operator[](const size_t i) const { return components_[i]; }
inline vec_t& operator[](const size_t i) { return components_[i]; }
...
private:
vec_t components_[N];
};
Define accessors based on N, as long as N < 3 :
x() when N >= 2 -> components_[0]
y() when N >= 2 -> components_[1]
z() when N >= 3 -> components_[2]
In addition, methods that work in specific dimensions such as Cross product would need to be made available depending on N. This should probably be feasible using enable_if.
Aliases would be defined for 2D and 3D vectors :
using Vector2D = VectorT<2>;
using Vector = VectorT<3>;
It's a good idea, but if we're overhauling the vector classes we may as well switch to GLM, which already does templated classes (albeit using template specializations for each number of components to improve performance and define APIs for each type): https://github.com/g-truc/glm
define APIs for each type
Do you mean using Vector to encapsulate calls to GLM ? If yes, I agree so to avoid spreading direct calls to GLM. This will also make it easier to migrate to different math libraries if ever needed.
In addition GLM could also be used for matrix operations but it's important to remember that some libraries handle matrix layout differently. For example, GLM matrices are column major while other libraries are row major. Using an API can help minimize impact and avoid potential issues that could arise from migrating to different math library.
Global Vector and Matrix functions could be moved in their respective classes.
class Vector : public glm::vec3
{
public:
using class_value = Vector;
using const_class_reference = const class_value&;
inline float DotProduct(const_class_reference a) const
{
return glm::dot(*this, a);
}
inline class_value CrossProduct(const_class_reference a) const
{
return glm::cross(*this, a);
}
};
In code :
auto c = a.CrossProduct(b);
Do you mean using Vector to encapsulate calls to GLM ?
No, i mean replacing the types altogether. There's no need to work around things like that.
I replaced custom math types based on the SDK with GLM in HLAM and it worked out fine once it was all standardized. The SDK is a bit different because we're accessing data from another library that uses older data types and stuff but it shouldn't be too much trouble to adapt everything.
You're going to have to update code no matter what you do when you swap out data types, so it's best to keep things simple.