Added editorconfig file for VS C++ code style formatting.

Applied C++ auto formatting.
This commit is contained in:
2022-08-08 00:20:45 -07:00
parent 870a796f39
commit 82a892cede
25 changed files with 2876 additions and 2480 deletions

136
.editorconfig Normal file
View File

@@ -0,0 +1,136 @@
# Visual Studio generated .editorconfig file with C++ settings.
root = true
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
# Visual C++ Code Style settings
cpp_generate_documentation_comments = xml
# Visual C++ Formatting settings
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = innermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = true
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = false
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = ignore
cpp_new_line_before_open_brace_type = ignore
cpp_new_line_before_open_brace_function = ignore
cpp_new_line_before_open_brace_block = false
cpp_new_line_before_open_brace_lambda = ignore
cpp_new_line_scope_braces_on_separate_lines = false
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = true
cpp_new_line_before_else = true
cpp_new_line_before_while_in_do_while = false
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = false
cpp_space_between_empty_parameter_list_parentheses = false
cpp_space_after_keywords_in_control_flow_statements = true
cpp_space_within_control_flow_statement_parentheses = false
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = false
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = false
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = left
cpp_space_around_ternary_operator = insert
cpp_wrap_preserve_blocks = one_liners
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
# Visual C++ Code Style settings
cpp_generate_documentation_comments = xml
# Visual C++ Formatting settings
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = outermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = true
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = false
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = same_line
cpp_new_line_before_open_brace_type = new_line
cpp_new_line_before_open_brace_function = new_line
cpp_new_line_before_open_brace_block = same_line
cpp_new_line_before_open_brace_lambda = same_line
cpp_new_line_scope_braces_on_separate_lines = true
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = false
cpp_new_line_before_else = false
cpp_new_line_before_while_in_do_while = false
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = false
cpp_space_between_empty_parameter_list_parentheses = false
cpp_space_after_keywords_in_control_flow_statements = true
cpp_space_within_control_flow_statement_parentheses = false
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = false
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = false
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = left
cpp_space_around_ternary_operator = insert
cpp_wrap_preserve_blocks = never

View File

@@ -43,61 +43,63 @@ namespace kraken {
class Matrix4; class Matrix4;
class AABB { class AABB
{
public: public:
Vector3 min; Vector3 min;
Vector3 max; Vector3 max;
void init(const Vector3 &minPoint, const Vector3 &maxPoint); void init(const Vector3& minPoint, const Vector3& maxPoint);
void init(const Vector3 &corner1, const Vector3 &corner2, const Matrix4 &modelMatrix); void init(const Vector3& corner1, const Vector3& corner2, const Matrix4& modelMatrix);
void init(); void init();
static AABB Create(const Vector3 &minPoint, const Vector3 &maxPoint); static AABB Create(const Vector3& minPoint, const Vector3& maxPoint);
static AABB Create(const Vector3 &corner1, const Vector3 &corner2, const Matrix4 &modelMatrix); static AABB Create(const Vector3& corner1, const Vector3& corner2, const Matrix4& modelMatrix);
static AABB Create(); static AABB Create();
void scale(const Vector3 &s); void scale(const Vector3& s);
void scale(float s); void scale(float s);
Vector3 center() const; Vector3 center() const;
Vector3 size() const; Vector3 size() const;
float volume() const; float volume() const;
bool intersects(const AABB& b) const; bool intersects(const AABB& b) const;
bool contains(const AABB &b) const; bool contains(const AABB& b) const;
bool contains(const Vector3 &v) const; bool contains(const Vector3& v) const;
bool intersectsLine(const Vector3 &v1, const Vector3 &v2) const; bool intersectsLine(const Vector3& v1, const Vector3& v2) const;
bool intersectsRay(const Vector3 &v1, const Vector3 &dir) const; bool intersectsRay(const Vector3& v1, const Vector3& dir) const;
bool intersectsSphere(const Vector3 &center, float radius) const; bool intersectsSphere(const Vector3& center, float radius) const;
void encapsulate(const AABB & b); void encapsulate(const AABB& b);
bool operator ==(const AABB& b) const; bool operator ==(const AABB& b) const;
bool operator !=(const AABB& b) const; bool operator !=(const AABB& b) const;
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
bool operator >(const AABB& b) const; bool operator >(const AABB& b) const;
bool operator <(const AABB& b) const; bool operator <(const AABB& b) const;
static AABB Infinite(); static AABB Infinite();
static AABB Zero(); static AABB Zero();
float longest_radius() const; float longest_radius() const;
Vector3 nearestPoint(const Vector3 & v) const; Vector3 nearestPoint(const Vector3& v) const;
}; };
static_assert(std::is_pod<AABB>::value, "kraken::AABB must be a POD type."); static_assert(std::is_pod<AABB>::value, "kraken::AABB must be a POD type.");
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::AABB> { struct hash<kraken::AABB>
public: {
size_t operator()(const kraken::AABB &s) const public:
{ size_t operator()(const kraken::AABB& s) const
size_t h1 = hash<kraken::Vector3>()(s.min); {
size_t h2 = hash<kraken::Vector3>()(s.max); size_t h1 = hash<kraken::Vector3>()(s.min);
return h1 ^ ( h2 << 1 ); size_t h2 = hash<kraken::Vector3>()(s.max);
} return h1 ^ (h2 << 1);
}; }
};
} // namespace std } // namespace std

View File

@@ -38,26 +38,27 @@ class KRNode;
namespace kraken { namespace kraken {
class HitInfo { class HitInfo
{
public: public:
HitInfo(); HitInfo();
HitInfo(const Vector3 &position, const Vector3 &normal, const float distance); HitInfo(const Vector3& position, const Vector3& normal, const float distance);
HitInfo(const Vector3 &position, const Vector3 &normal, const float distance, KRNode *node); HitInfo(const Vector3& position, const Vector3& normal, const float distance, KRNode* node);
~HitInfo(); ~HitInfo();
Vector3 getPosition() const; Vector3 getPosition() const;
Vector3 getNormal() const; Vector3 getNormal() const;
float getDistance() const; float getDistance() const;
KRNode *getNode() const; KRNode* getNode() const;
bool didHit() const; bool didHit() const;
HitInfo& operator =(const HitInfo& b); HitInfo& operator =(const HitInfo& b);
private: private:
KRNode *m_node; KRNode* m_node;
Vector3 m_position; Vector3 m_position;
Vector3 m_normal; Vector3 m_normal;
float m_distance; float m_distance;
}; };
} // namespace kraken } // namespace kraken

View File

@@ -36,54 +36,57 @@
namespace kraken { namespace kraken {
class Matrix2 { class Matrix2
{
public: public:
union { union
struct { {
struct
{
Vector2 axis_x, axis_y; Vector2 axis_x, axis_y;
}; };
// Matrix components, in column-major order // Matrix components, in column-major order
float c[4]; float c[4];
}; };
// Default initializer - Creates an identity matrix // Default initializer - Creates an identity matrix
void init(); void init();
void init(float *pMat);
void init(const Vector2 &new_axis_x, const Vector2 &new_axis_y);
void init(const Matrix2 &m); void init(float* pMat);
void init(const Vector2& new_axis_x, const Vector2& new_axis_y);
void init(const Matrix2& m);
// Overload comparison operator // Overload comparison operator
bool operator==(const Matrix2 &m) const; bool operator==(const Matrix2& m) const;
// Overload compound multiply operator // Overload compound multiply operator
Matrix2& operator*=(const Matrix2 &m); Matrix2& operator*=(const Matrix2& m);
float& operator[](unsigned i); float& operator[](unsigned i);
float operator[](unsigned i) const; float operator[](unsigned i) const;
// Overload multiply operator // Overload multiply operator
//Matrix4& operator*(const Matrix4 &m); //Matrix4& operator*(const Matrix4 &m);
Matrix2 operator*(const Matrix2 &m) const; Matrix2 operator*(const Matrix2& m) const;
float *getPointer(); float* getPointer();
void scale(float x, float y); void scale(float x, float y);
void scale(const Vector2 &v); void scale(const Vector2& v);
void scale(float s); void scale(float s);
void rotate(float angle); void rotate(float angle);
bool invert(); bool invert();
void transpose(); void transpose();
static Matrix2 Invert(const Matrix2 &m); static Matrix2 Invert(const Matrix2& m);
static Matrix2 Transpose(const Matrix2 &m); static Matrix2 Transpose(const Matrix2& m);
static Vector2 Dot(const Matrix2 &m, const Vector2 &v); static Vector2 Dot(const Matrix2& m, const Vector2& v);
static Matrix2 Rotation(float); static Matrix2 Rotation(float);
static Matrix2 Scaling(const Vector2 &v); static Matrix2 Scaling(const Vector2& v);
static Matrix2 Identity(); static Matrix2 Identity();
}; };
static_assert(std::is_pod<Matrix2>::value, "kraken::Matrix2 must be a POD type."); static_assert(std::is_pod<Matrix2>::value, "kraken::Matrix2 must be a POD type.");
@@ -91,16 +94,17 @@ static_assert(std::is_pod<Matrix2>::value, "kraken::Matrix2 must be a POD type."
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Matrix2> { struct hash<kraken::Matrix2>
public: {
size_t operator()(const kraken::Matrix2 &s) const public:
{ size_t operator()(const kraken::Matrix2& s) const
size_t h1 = hash<kraken::Vector2>()(s.axis_x); {
size_t h2 = hash<kraken::Vector2>()(s.axis_y); size_t h1 = hash<kraken::Vector2>()(s.axis_x);
return h1 ^ (h2 << 1); size_t h2 = hash<kraken::Vector2>()(s.axis_y);
} return h1 ^ (h2 << 1);
}; }
};
} // namespace std } // namespace std
#endif // KRAKEN_MATRIX2_H #endif // KRAKEN_MATRIX2_H

View File

@@ -37,55 +37,58 @@
namespace kraken { namespace kraken {
class Matrix2x3 { class Matrix2x3
{
public: public:
union { union
struct { {
struct
{
Vector2 axis_x, axis_y, transform; Vector2 axis_x, axis_y, transform;
}; };
// Matrix components, in column-major order // Matrix components, in column-major order
float c[6]; float c[6];
}; };
// Default initializer - Creates an identity matrix // Default initializer - Creates an identity matrix
void init(); void init();
void init(float *pMat);
void init(const Vector2 &new_axis_x, const Vector2 &new_axis_y, const Vector2 &new_transform);
void init(const Matrix2x3 &m); void init(float* pMat);
void init(const Vector2& new_axis_x, const Vector2& new_axis_y, const Vector2& new_transform);
void init(const Matrix2x3& m);
// Overload comparison operator // Overload comparison operator
bool operator==(const Matrix2x3 &m) const; bool operator==(const Matrix2x3& m) const;
// Overload compound multiply operator // Overload compound multiply operator
Matrix2x3& operator*=(const Matrix2x3 &m); Matrix2x3& operator*=(const Matrix2x3& m);
float& operator[](unsigned i); float& operator[](unsigned i);
float operator[](unsigned i) const; float operator[](unsigned i) const;
// Overload multiply operator // Overload multiply operator
Matrix2x3 operator*(const Matrix2x3 &m) const; Matrix2x3 operator*(const Matrix2x3& m) const;
float *getPointer(); float* getPointer();
void translate(float x, float y); void translate(float x, float y);
void translate(const Vector2 &v); void translate(const Vector2& v);
void scale(float x, float y); void scale(float x, float y);
void scale(const Vector2 &v); void scale(const Vector2& v);
void scale(float s); void scale(float s);
void rotate(float angle); void rotate(float angle);
bool invert(); bool invert();
static Vector2 DotNoTranslate(const Matrix2x3 &m, const Vector2 &v); // Dot product without including translation; useful for transforming normals and tangents static Vector2 DotNoTranslate(const Matrix2x3& m, const Vector2& v); // Dot product without including translation; useful for transforming normals and tangents
static Matrix2x3 Invert(const Matrix2x3 &m); static Matrix2x3 Invert(const Matrix2x3& m);
static Vector2 Dot(const Matrix2x3 &m, const Vector2 &v); static Vector2 Dot(const Matrix2x3& m, const Vector2& v);
static Matrix2x3 Translation(const Vector2 &v); static Matrix2x3 Translation(const Vector2& v);
static Matrix2x3 Rotation(float angle); static Matrix2x3 Rotation(float angle);
static Matrix2x3 Scaling(const Vector2 &v); static Matrix2x3 Scaling(const Vector2& v);
static Matrix2x3 Identity(); static Matrix2x3 Identity();
}; };
static_assert(std::is_pod<Matrix2x3>::value, "kraken::Matrix2x3 must be a POD type."); static_assert(std::is_pod<Matrix2x3>::value, "kraken::Matrix2x3 must be a POD type.");
@@ -93,17 +96,18 @@ static_assert(std::is_pod<Matrix2x3>::value, "kraken::Matrix2x3 must be a POD ty
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Matrix2x3> { struct hash<kraken::Matrix2x3>
public: {
size_t operator()(const kraken::Matrix2x3 &s) const public:
{ size_t operator()(const kraken::Matrix2x3& s) const
size_t h1 = hash<kraken::Vector2>()(s.axis_x); {
size_t h2 = hash<kraken::Vector2>()(s.axis_y); size_t h1 = hash<kraken::Vector2>()(s.axis_x);
size_t h3 = hash<kraken::Vector2>()(s.transform); size_t h2 = hash<kraken::Vector2>()(s.axis_y);
return h1 ^ (h2 << 1) ^ (h3 << 2); size_t h3 = hash<kraken::Vector2>()(s.transform);
} return h1 ^ (h2 << 1) ^ (h3 << 2);
}; }
};
} // namespace std } // namespace std
#endif // KRAKEN_MATRIX2X3_H #endif // KRAKEN_MATRIX2X3_H

View File

@@ -38,7 +38,8 @@
namespace kraken { namespace kraken {
enum class AXIS { enum class AXIS
{
X_AXIS, X_AXIS,
Y_AXIS, Y_AXIS,
Z_AXIS Z_AXIS
@@ -46,68 +47,71 @@ enum class AXIS {
class Quaternion; class Quaternion;
class Matrix4 { class Matrix4
{
public: public:
union { union
struct { {
struct
{
Vector4 axis_x, axis_y, axis_z, transform; Vector4 axis_x, axis_y, axis_z, transform;
}; };
// Matrix components, in column-major order // Matrix components, in column-major order
float c[16]; float c[16];
}; };
// Default initializer - Creates an identity matrix // Default initializer - Creates an identity matrix
void init(); void init();
void init(float *pMat);
void init(const Vector3 &new_axis_x, const Vector3 &new_axis_y, const Vector3 &new_axis_z, const Vector3 &new_transform);
void init(const Matrix4 &m);
static Matrix4 Create(float *pMat); void init(float* pMat);
static Matrix4 Create(const Vector3 &new_axis_x, const Vector3 &new_axis_y, const Vector3 &new_axis_z, const Vector3 &new_transform); void init(const Vector3& new_axis_x, const Vector3& new_axis_y, const Vector3& new_axis_z, const Vector3& new_transform);
void init(const Matrix4& m);
static Matrix4 Create(float* pMat);
static Matrix4 Create(const Vector3& new_axis_x, const Vector3& new_axis_y, const Vector3& new_axis_z, const Vector3& new_transform);
// Overload comparison operator // Overload comparison operator
bool operator==(const Matrix4 &m) const; bool operator==(const Matrix4& m) const;
// Overload compound multiply operator // Overload compound multiply operator
Matrix4& operator*=(const Matrix4 &m); Matrix4& operator*=(const Matrix4& m);
float& operator[](unsigned i); float& operator[](unsigned i);
float operator[](unsigned i) const; float operator[](unsigned i) const;
// Overload multiply operator // Overload multiply operator
//Matrix4& operator*(const Matrix4 &m); //Matrix4& operator*(const Matrix4 &m);
Matrix4 operator*(const Matrix4 &m) const; Matrix4 operator*(const Matrix4& m) const;
float *getPointer(); float* getPointer();
void perspective(float fov, float aspect, float nearz, float farz); void perspective(float fov, float aspect, float nearz, float farz);
void ortho(float left, float right, float top, float bottom, float nearz, float farz); void ortho(float left, float right, float top, float bottom, float nearz, float farz);
void translate(float x, float y, float z); void translate(float x, float y, float z);
void translate(const Vector3 &v); void translate(const Vector3& v);
void scale(float x, float y, float z); void scale(float x, float y, float z);
void scale(const Vector3 &v); void scale(const Vector3& v);
void scale(float s); void scale(float s);
void rotate(float angle, AXIS axis); void rotate(float angle, AXIS axis);
void rotate(const Quaternion &q); void rotate(const Quaternion& q);
void bias(); void bias();
bool invert(); bool invert();
void transpose(); void transpose();
static Vector3 DotNoTranslate(const Matrix4 &m, const Vector3 &v); // Dot product without including translation; useful for transforming normals and tangents static Vector3 DotNoTranslate(const Matrix4& m, const Vector3& v); // Dot product without including translation; useful for transforming normals and tangents
static Matrix4 Invert(const Matrix4 &m); static Matrix4 Invert(const Matrix4& m);
static Matrix4 Transpose(const Matrix4 &m); static Matrix4 Transpose(const Matrix4& m);
static Vector3 Dot(const Matrix4 &m, const Vector3 &v); static Vector3 Dot(const Matrix4& m, const Vector3& v);
static Vector4 Dot4(const Matrix4 &m, const Vector4 &v); static Vector4 Dot4(const Matrix4& m, const Vector4& v);
static float DotW(const Matrix4 &m, const Vector3 &v); static float DotW(const Matrix4& m, const Vector3& v);
static Vector3 DotWDiv(const Matrix4 &m, const Vector3 &v); static Vector3 DotWDiv(const Matrix4& m, const Vector3& v);
static Matrix4 LookAt(const Vector3 &cameraPos, const Vector3 &lookAtPos, const Vector3 &upDirection); static Matrix4 LookAt(const Vector3& cameraPos, const Vector3& lookAtPos, const Vector3& upDirection);
static Matrix4 Translation(const Vector3 &v); static Matrix4 Translation(const Vector3& v);
static Matrix4 Rotation(const Vector3 &v); static Matrix4 Rotation(const Vector3& v);
static Matrix4 Scaling(const Vector3 &v); static Matrix4 Scaling(const Vector3& v);
static Matrix4 Identity(); static Matrix4 Identity();
}; };
static_assert(std::is_pod<Matrix4>::value, "kraken::Matrix4 must be a POD type."); static_assert(std::is_pod<Matrix4>::value, "kraken::Matrix4 must be a POD type.");
@@ -115,18 +119,19 @@ static_assert(std::is_pod<Matrix4>::value, "kraken::Matrix4 must be a POD type."
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Matrix4> { struct hash<kraken::Matrix4>
public: {
size_t operator()(const kraken::Matrix4 &s) const public:
{ size_t operator()(const kraken::Matrix4& s) const
size_t h1 = hash<kraken::Vector4>()(s.axis_x); {
size_t h2 = hash<kraken::Vector4>()(s.axis_y); size_t h1 = hash<kraken::Vector4>()(s.axis_x);
size_t h3 = hash<kraken::Vector4>()(s.axis_z); size_t h2 = hash<kraken::Vector4>()(s.axis_y);
size_t h4 = hash<kraken::Vector4>()(s.transform); size_t h3 = hash<kraken::Vector4>()(s.axis_z);
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3); size_t h4 = hash<kraken::Vector4>()(s.transform);
} return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
}; }
};
} // namespace std } // namespace std
#endif // KRAKEN_MATRIX4_H #endif // KRAKEN_MATRIX4_H

View File

@@ -36,10 +36,13 @@
namespace kraken { namespace kraken {
class Quaternion { class Quaternion
{
public: public:
union { union
struct { {
struct
{
float w, x, y, z; float w, x, y, z;
}; };
float c[4]; float c[4];
@@ -48,71 +51,72 @@ public:
void init(); void init();
void init(float w, float x, float y, float z); void init(float w, float x, float y, float z);
void init(const Quaternion& p); void init(const Quaternion& p);
void init(const Vector3 &euler); void init(const Vector3& euler);
void init(const Vector3 &from_vector, const Vector3 &to_vector); void init(const Vector3& from_vector, const Vector3& to_vector);
static Quaternion Create(); static Quaternion Create();
static Quaternion Create(float w, float x, float y, float z); static Quaternion Create(float w, float x, float y, float z);
static Quaternion Create(const Quaternion& p); static Quaternion Create(const Quaternion& p);
static Quaternion Create(const Vector3 &euler); static Quaternion Create(const Vector3& euler);
static Quaternion Create(const Vector3 &from_vector, const Vector3 &to_vector); static Quaternion Create(const Vector3& from_vector, const Vector3& to_vector);
Quaternion operator +(const Quaternion &v) const; Quaternion operator +(const Quaternion& v) const;
Quaternion operator -(const Quaternion &v) const; Quaternion operator -(const Quaternion& v) const;
Quaternion operator +() const; Quaternion operator +() const;
Quaternion operator -() const; Quaternion operator -() const;
Quaternion operator *(const Quaternion &v); Quaternion operator *(const Quaternion& v);
Quaternion operator *(float num) const; Quaternion operator *(float num) const;
Quaternion operator /(float num) const; Quaternion operator /(float num) const;
Quaternion& operator +=(const Quaternion& v); Quaternion& operator +=(const Quaternion& v);
Quaternion& operator -=(const Quaternion& v); Quaternion& operator -=(const Quaternion& v);
Quaternion& operator *=(const Quaternion& v); Quaternion& operator *=(const Quaternion& v);
Quaternion& operator *=(const float& v); Quaternion& operator *=(const float& v);
Quaternion& operator /=(const float& v); Quaternion& operator /=(const float& v);
friend bool operator ==(Quaternion &v1, Quaternion &v2); friend bool operator ==(Quaternion& v1, Quaternion& v2);
friend bool operator !=(Quaternion &v1, Quaternion &v2); friend bool operator !=(Quaternion& v1, Quaternion& v2);
float& operator [](unsigned i); float& operator [](unsigned i);
float operator [](unsigned i) const; float operator [](unsigned i) const;
void setEulerXYZ(const Vector3 &euler); void setEulerXYZ(const Vector3& euler);
void setEulerZYX(const Vector3 &euler); void setEulerZYX(const Vector3& euler);
Vector3 eulerXYZ() const; Vector3 eulerXYZ() const;
Matrix4 rotationMatrix() const; Matrix4 rotationMatrix() const;
void normalize(); void normalize();
static Quaternion Normalize(const Quaternion &v1); static Quaternion Normalize(const Quaternion& v1);
void conjugate(); void conjugate();
static Quaternion Conjugate(const Quaternion &v1); static Quaternion Conjugate(const Quaternion& v1);
void invert(); void invert();
static Quaternion Invert(const Quaternion &v1); static Quaternion Invert(const Quaternion& v1);
static Quaternion FromAngleAxis(const Vector3 &axis, float angle); static Quaternion FromAngleAxis(const Vector3& axis, float angle);
static Quaternion FromRotationMatrix(const Matrix4 &m); static Quaternion FromRotationMatrix(const Matrix4& m);
static Quaternion Lerp(const Quaternion &a, const Quaternion &b, float t); static Quaternion Lerp(const Quaternion& a, const Quaternion& b, float t);
static Quaternion Slerp(const Quaternion &a, const Quaternion &b, float t); static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float t);
static float Dot(const Quaternion &v1, const Quaternion &v2); static float Dot(const Quaternion& v1, const Quaternion& v2);
}; };
static_assert(std::is_pod<Quaternion>::value, "kraken::Quaternion must be a POD type."); static_assert(std::is_pod<Quaternion>::value, "kraken::Quaternion must be a POD type.");
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Quaternion> { struct hash<kraken::Quaternion>
public: {
size_t operator()(const kraken::Quaternion &s) const public:
{ size_t operator()(const kraken::Quaternion& s) const
size_t h1 = hash<float>()(s.c[0]); {
size_t h2 = hash<float>()(s.c[1]); size_t h1 = hash<float>()(s.c[0]);
size_t h3 = hash<float>()(s.c[2]); size_t h2 = hash<float>()(s.c[1]);
size_t h4 = hash<float>()(s.c[3]); size_t h3 = hash<float>()(s.c[2]);
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3); size_t h4 = hash<float>()(s.c[3]);
} return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
}; }
};
} // namespace std } // namespace std
#endif // KRAKEN_QUATERNION_H #endif // KRAKEN_QUATERNION_H

View File

@@ -34,8 +34,8 @@
namespace kraken { namespace kraken {
float SmoothStep(float a, float b, float t); float SmoothStep(float a, float b, float t);
float Lerp(float a, float b, float t); float Lerp(float a, float b, float t);
}; // namespace kraken }; // namespace kraken

View File

@@ -41,40 +41,41 @@ class Triangle3
public: public:
Vector3 vert[3]; Vector3 vert[3];
void init(const Triangle3 &tri); void init(const Triangle3& tri);
void init(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3); void init(const Vector3& v1, const Vector3& v2, const Vector3& v3);
static Triangle3 Create(const Triangle3 &tri); static Triangle3 Create(const Triangle3& tri);
static Triangle3 Create(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3); static Triangle3 Create(const Vector3& v1, const Vector3& v2, const Vector3& v3);
Vector3 calculateNormal() const; Vector3 calculateNormal() const;
bool operator ==(const Triangle3& b) const; bool operator ==(const Triangle3& b) const;
bool operator !=(const Triangle3& b) const; bool operator !=(const Triangle3& b) const;
Vector3& operator[](unsigned int i); Vector3& operator[](unsigned int i);
Vector3 operator[](unsigned int i) const; Vector3 operator[](unsigned int i) const;
bool rayCast(const Vector3 &start, const Vector3 &dir, Vector3 &hit_point) const; bool rayCast(const Vector3& start, const Vector3& dir, Vector3& hit_point) const;
bool sphereCast(const Vector3 &start, const Vector3 &dir, float radius, Vector3 &hit_point, float &hit_distance) const; bool sphereCast(const Vector3& start, const Vector3& dir, float radius, Vector3& hit_point, float& hit_distance) const;
bool containsPoint(const Vector3 &p) const; bool containsPoint(const Vector3& p) const;
Vector3 closestPointOnTriangle(const Vector3 &p) const; Vector3 closestPointOnTriangle(const Vector3& p) const;
}; };
static_assert(std::is_pod<Triangle3>::value, "kraken::Triangle3 must be a POD type."); static_assert(std::is_pod<Triangle3>::value, "kraken::Triangle3 must be a POD type.");
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Triangle3> { struct hash<kraken::Triangle3>
public: {
size_t operator()(const kraken::Triangle3 &s) const public:
{ size_t operator()(const kraken::Triangle3& s) const
size_t h1 = hash<kraken::Vector3>()(s.vert[0]); {
size_t h2 = hash<kraken::Vector3>()(s.vert[1]); size_t h1 = hash<kraken::Vector3>()(s.vert[0]);
size_t h3 = hash<kraken::Vector3>()(s.vert[2]); size_t h2 = hash<kraken::Vector3>()(s.vert[1]);
return h1 ^ (h2 << 1) ^ (h3 << 2); size_t h3 = hash<kraken::Vector3>()(s.vert[2]);
} return h1 ^ (h2 << 1) ^ (h3 << 2);
}; }
};
} // namespace std } // namespace std
#endif // KRAKEN_TRIANGLE3_H #endif // KRAKEN_TRIANGLE3_H

View File

@@ -38,65 +38,68 @@
namespace kraken { namespace kraken {
class Vector2 { class Vector2
{
public: public:
union { union
struct { {
struct
{
float x, y; float x, y;
}; };
float c[2]; float c[2];
}; };
void init(); void init();
void init(float X, float Y); void init(float X, float Y);
void init(float v); void init(float v);
void init(float *v); void init(float* v);
void init(const Vector2 &v); void init(const Vector2& v);
static Vector2 Create(); static Vector2 Create();
static Vector2 Create(float X, float Y); static Vector2 Create(float X, float Y);
static Vector2 Create(float v); static Vector2 Create(float v);
static Vector2 Create(float *v); static Vector2 Create(float* v);
static Vector2 Create(const Vector2 &v); static Vector2 Create(const Vector2& v);
// Vector2 swizzle getters // Vector2 swizzle getters
Vector2 yx() const; Vector2 yx() const;
// Vector2 swizzle setters // Vector2 swizzle setters
void yx(const Vector2 &v); void yx(const Vector2& v);
Vector2 operator +(const Vector2& b) const; Vector2 operator +(const Vector2& b) const;
Vector2 operator -(const Vector2& b) const; Vector2 operator -(const Vector2& b) const;
Vector2 operator +() const; Vector2 operator +() const;
Vector2 operator -() const; Vector2 operator -() const;
Vector2 operator *(const float v) const; Vector2 operator *(const float v) const;
Vector2 operator /(const float v) const; Vector2 operator /(const float v) const;
Vector2& operator +=(const Vector2& b); Vector2& operator +=(const Vector2& b);
Vector2& operator -=(const Vector2& b); Vector2& operator -=(const Vector2& b);
Vector2& operator *=(const float v); Vector2& operator *=(const float v);
Vector2& operator /=(const float v); Vector2& operator /=(const float v);
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
bool operator >(const Vector2& b) const; bool operator >(const Vector2& b) const;
bool operator <(const Vector2& b) const; bool operator <(const Vector2& b) const;
bool operator ==(const Vector2& b) const; bool operator ==(const Vector2& b) const;
bool operator !=(const Vector2& b) const; bool operator !=(const Vector2& b) const;
float& operator[](unsigned i); float& operator[](unsigned i);
float operator[](unsigned i) const; float operator[](unsigned i) const;
float sqrMagnitude() const; float sqrMagnitude() const;
float magnitude() const; float magnitude() const;
void normalize(); void normalize();
static Vector2 Normalize(const Vector2 &v); static Vector2 Normalize(const Vector2& v);
static float Cross(const Vector2 &v1, const Vector2 &v2); static float Cross(const Vector2& v1, const Vector2& v2);
static float Dot(const Vector2 &v1, const Vector2 &v2); static float Dot(const Vector2& v1, const Vector2& v2);
static Vector2 Min(const Vector2 &v1, const Vector2 &v2); static Vector2 Min(const Vector2& v1, const Vector2& v2);
static Vector2 Max(const Vector2 &v1, const Vector2 &v2); static Vector2 Max(const Vector2& v1, const Vector2& v2);
static Vector2 Min(); static Vector2 Min();
static Vector2 Max(); static Vector2 Max();
static Vector2 Zero(); static Vector2 Zero();
@@ -107,16 +110,17 @@ static_assert(std::is_pod<Vector2>::value, "kraken::Vector2 must be a POD type."
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Vector2> { struct hash<kraken::Vector2>
public: {
size_t operator()(const kraken::Vector2 &s) const public:
{ size_t operator()(const kraken::Vector2& s) const
size_t h1 = hash<float>()(s.x); {
size_t h2 = hash<float>()(s.y); size_t h1 = hash<float>()(s.x);
return h1 ^ (h2 << 1); size_t h2 = hash<float>()(s.y);
} return h1 ^ (h2 << 1);
}; }
};
} // namespace std } // namespace std
#endif // KRAKEN_VECTOR2_H #endif // KRAKEN_VECTOR2_H

View File

@@ -37,11 +37,14 @@
namespace kraken { namespace kraken {
class Vector2i { class Vector2i
{
public: public:
union { union
struct { {
struct
{
int x, y; int x, y;
}; };
int c[2]; int c[2];
@@ -50,52 +53,52 @@ public:
void init(); void init();
void init(int X, int Y); void init(int X, int Y);
void init(int v); void init(int v);
void init(int *v); void init(int* v);
void init(const Vector2i &v); void init(const Vector2i& v);
static Vector2i Create(); static Vector2i Create();
static Vector2i Create(int X, int Y); static Vector2i Create(int X, int Y);
static Vector2i Create(int v); static Vector2i Create(int v);
static Vector2i Create(int *v); static Vector2i Create(int* v);
static Vector2i Create(const Vector2i &v); static Vector2i Create(const Vector2i& v);
// Vector2 swizzle getters // Vector2 swizzle getters
Vector2i yx() const; Vector2i yx() const;
// Vector2 swizzle setters // Vector2 swizzle setters
void yx(const Vector2i &v); void yx(const Vector2i& v);
Vector2i operator +(const Vector2i& b) const; Vector2i operator +(const Vector2i& b) const;
Vector2i operator -(const Vector2i& b) const; Vector2i operator -(const Vector2i& b) const;
Vector2i operator +() const; Vector2i operator +() const;
Vector2i operator -() const; Vector2i operator -() const;
Vector2i operator *(const int v) const; Vector2i operator *(const int v) const;
Vector2i operator /(const int v) const; Vector2i operator /(const int v) const;
Vector2i& operator +=(const Vector2i& b); Vector2i& operator +=(const Vector2i& b);
Vector2i& operator -=(const Vector2i& b); Vector2i& operator -=(const Vector2i& b);
Vector2i& operator *=(const int v); Vector2i& operator *=(const int v);
Vector2i& operator /=(const int v); Vector2i& operator /=(const int v);
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
bool operator >(const Vector2i& b) const; bool operator >(const Vector2i& b) const;
bool operator <(const Vector2i& b) const; bool operator <(const Vector2i& b) const;
bool operator ==(const Vector2i& b) const; bool operator ==(const Vector2i& b) const;
bool operator !=(const Vector2i& b) const; bool operator !=(const Vector2i& b) const;
int& operator[](unsigned i); int& operator[](unsigned i);
int operator[](unsigned i) const; int operator[](unsigned i) const;
int sqrMagnitude() const; int sqrMagnitude() const;
int magnitude() const; int magnitude() const;
void normalize(); void normalize();
static Vector2i Normalize(const Vector2i &v); static Vector2i Normalize(const Vector2i& v);
static int Cross(const Vector2i &v1, const Vector2i &v2); static int Cross(const Vector2i& v1, const Vector2i& v2);
static int Dot(const Vector2i &v1, const Vector2i &v2); static int Dot(const Vector2i& v1, const Vector2i& v2);
static Vector2i Min(const Vector2i &v1, const Vector2i &v2); static Vector2i Min(const Vector2i& v1, const Vector2i& v2);
static Vector2i Max(const Vector2i &v1, const Vector2i &v2); static Vector2i Max(const Vector2i& v1, const Vector2i& v2);
static Vector2i Min(); static Vector2i Min();
static Vector2i Max(); static Vector2i Max();
@@ -107,14 +110,15 @@ static_assert(std::is_pod<Vector2i>::value, "kraken::Vector2i must be a POD type
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Vector2i> { struct hash<kraken::Vector2i>
public: {
size_t operator()(const kraken::Vector2i &s) const public:
{ size_t operator()(const kraken::Vector2i& s) const
size_t h1 = hash<int>()(s.x); {
size_t h2 = hash<int>()(s.y); size_t h1 = hash<int>()(s.x);
return h1 ^ (h2 << 1); size_t h2 = hash<int>()(s.y);
} return h1 ^ (h2 << 1);
}; }
};
} // namespace std } // namespace std

View File

@@ -38,32 +38,35 @@
namespace kraken { namespace kraken {
class Vector3 { class Vector3
{
public: public:
union { union
struct { {
struct
{
float x, y, z; float x, y, z;
}; };
float c[3]; float c[3];
}; };
void init(); void init();
void init(float X, float Y, float Z); void init(float X, float Y, float Z);
void init(float v); void init(float v);
void init(float *v); void init(float* v);
void init(double *v); void init(double* v);
void init(const Vector3 &v); void init(const Vector3& v);
void init(const Vector4 &v); void init(const Vector4& v);
static Vector3 Create(); static Vector3 Create();
static Vector3 Create(float X, float Y, float Z); static Vector3 Create(float X, float Y, float Z);
static Vector3 Create(float v); static Vector3 Create(float v);
static Vector3 Create(float *v); static Vector3 Create(float* v);
static Vector3 Create(double *v); static Vector3 Create(double* v);
static Vector3 Create(const Vector3 &v); static Vector3 Create(const Vector3& v);
static Vector3 Create(const Vector4 &v); static Vector3 Create(const Vector4& v);
// Vector2 swizzle getters // Vector2 swizzle getters
Vector2 xx() const; Vector2 xx() const;
Vector2 xy() const; Vector2 xy() const;
@@ -74,15 +77,15 @@ public:
Vector2 zx() const; Vector2 zx() const;
Vector2 zy() const; Vector2 zy() const;
Vector2 zz() const; Vector2 zz() const;
// Vector2 swizzle setters // Vector2 swizzle setters
void xy(const Vector2 &v); void xy(const Vector2& v);
void xz(const Vector2 &v); void xz(const Vector2& v);
void yx(const Vector2 &v); void yx(const Vector2& v);
void yz(const Vector2 &v); void yz(const Vector2& v);
void zx(const Vector2 &v); void zx(const Vector2& v);
void zy(const Vector2 &v); void zy(const Vector2& v);
Vector3& operator =(const Vector4& b); Vector3& operator =(const Vector4& b);
Vector3 operator +(const Vector3& b) const; Vector3 operator +(const Vector3& b) const;
Vector3 operator -(const Vector3& b) const; Vector3 operator -(const Vector3& b) const;
@@ -90,33 +93,33 @@ public:
Vector3 operator -() const; Vector3 operator -() const;
Vector3 operator *(const float v) const; Vector3 operator *(const float v) const;
Vector3 operator /(const float v) const; Vector3 operator /(const float v) const;
Vector3& operator +=(const Vector3& b); Vector3& operator +=(const Vector3& b);
Vector3& operator -=(const Vector3& b); Vector3& operator -=(const Vector3& b);
Vector3& operator *=(const float v); Vector3& operator *=(const float v);
Vector3& operator /=(const float v); Vector3& operator /=(const float v);
bool operator ==(const Vector3& b) const; bool operator ==(const Vector3& b) const;
bool operator !=(const Vector3& b) const; bool operator !=(const Vector3& b) const;
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
bool operator >(const Vector3& b) const; bool operator >(const Vector3& b) const;
bool operator <(const Vector3& b) const; bool operator <(const Vector3& b) const;
float& operator[](unsigned i); float& operator[](unsigned i);
float operator[](unsigned i) const; float operator[](unsigned i) const;
float sqrMagnitude() const; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function) float sqrMagnitude() const; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
float magnitude() const; float magnitude() const;
void scale(const Vector3 &v); void scale(const Vector3& v);
void normalize(); void normalize();
static Vector3 Normalize(const Vector3 &v); static Vector3 Normalize(const Vector3& v);
static Vector3 Cross(const Vector3 &v1, const Vector3 &v2); static Vector3 Cross(const Vector3& v1, const Vector3& v2);
static float Dot(const Vector3 &v1, const Vector3 &v2); static float Dot(const Vector3& v1, const Vector3& v2);
static Vector3 Min(const Vector3 &v1, const Vector3 &v2); static Vector3 Min(const Vector3& v1, const Vector3& v2);
static Vector3 Max(const Vector3 &v1, const Vector3 &v2); static Vector3 Max(const Vector3& v1, const Vector3& v2);
static Vector3 Min(); static Vector3 Min();
static Vector3 Max(); static Vector3 Max();
@@ -128,25 +131,26 @@ public:
static Vector3 Down(); static Vector3 Down();
static Vector3 Left(); static Vector3 Left();
static Vector3 Right(); static Vector3 Right();
static Vector3 Scale(const Vector3 &v1, const Vector3 &v2); static Vector3 Scale(const Vector3& v1, const Vector3& v2);
static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2, float d); static Vector3 Lerp(const Vector3& v1, const Vector3& v2, float d);
static Vector3 Slerp(const Vector3 &v1, const Vector3 &v2, float d); static Vector3 Slerp(const Vector3& v1, const Vector3& v2, float d);
static void OrthoNormalize(Vector3 &normal, Vector3 &tangent); // Gram-Schmidt Orthonormalization static void OrthoNormalize(Vector3& normal, Vector3& tangent); // Gram-Schmidt Orthonormalization
}; };
static_assert(std::is_pod<Vector3>::value, "kraken::Vector3 must be a POD type."); static_assert(std::is_pod<Vector3>::value, "kraken::Vector3 must be a POD type.");
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Vector3> { struct hash<kraken::Vector3>
public: {
size_t operator()(const kraken::Vector3 &s) const public:
{ size_t operator()(const kraken::Vector3& s) const
size_t h1 = hash<float>()(s.x); {
size_t h2 = hash<float>()(s.y); size_t h1 = hash<float>()(s.x);
size_t h3 = hash<float>()(s.z); size_t h2 = hash<float>()(s.y);
return h1 ^ (h2 << 1) ^ (h3 << 2); size_t h3 = hash<float>()(s.z);
} return h1 ^ (h2 << 1) ^ (h3 << 2);
}; }
};
} // namespace std } // namespace std

View File

@@ -37,11 +37,14 @@ namespace kraken {
class Vector3; class Vector3;
class Vector4 { class Vector4
{
public: public:
union { union
struct { {
struct
{
float x, y, z, w; float x, y, z, w;
}; };
float c[4]; float c[4];
@@ -50,47 +53,47 @@ public:
void init(); void init();
void init(float X, float Y, float Z, float W); void init(float X, float Y, float Z, float W);
void init(float v); void init(float v);
void init(float *v); void init(float* v);
void init(const Vector4 &v); void init(const Vector4& v);
void init(const Vector3 &v, float W); void init(const Vector3& v, float W);
static Vector4 Create(); static Vector4 Create();
static Vector4 Create(float X, float Y, float Z, float W); static Vector4 Create(float X, float Y, float Z, float W);
static Vector4 Create(float v); static Vector4 Create(float v);
static Vector4 Create(float *v); static Vector4 Create(float* v);
static Vector4 Create(const Vector4 &v); static Vector4 Create(const Vector4& v);
static Vector4 Create(const Vector3 &v, float W); static Vector4 Create(const Vector3& v, float W);
Vector4 operator +(const Vector4& b) const; Vector4 operator +(const Vector4& b) const;
Vector4 operator -(const Vector4& b) const; Vector4 operator -(const Vector4& b) const;
Vector4 operator +() const; Vector4 operator +() const;
Vector4 operator -() const; Vector4 operator -() const;
Vector4 operator *(const float v) const; Vector4 operator *(const float v) const;
Vector4 operator /(const float v) const; Vector4 operator /(const float v) const;
Vector4& operator +=(const Vector4& b); Vector4& operator +=(const Vector4& b);
Vector4& operator -=(const Vector4& b); Vector4& operator -=(const Vector4& b);
Vector4& operator *=(const float v); Vector4& operator *=(const float v);
Vector4& operator /=(const float v); Vector4& operator /=(const float v);
bool operator ==(const Vector4& b) const; bool operator ==(const Vector4& b) const;
bool operator !=(const Vector4& b) const; bool operator !=(const Vector4& b) const;
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
bool operator >(const Vector4& b) const; bool operator >(const Vector4& b) const;
bool operator <(const Vector4& b) const; bool operator <(const Vector4& b) const;
float& operator[](unsigned i); float& operator[](unsigned i);
float operator[](unsigned i) const; float operator[](unsigned i) const;
float sqrMagnitude() const; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function) float sqrMagnitude() const; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
float magnitude() const; float magnitude() const;
void normalize(); void normalize();
static Vector4 Normalize(const Vector4 &v); static Vector4 Normalize(const Vector4& v);
static float Dot(const Vector4 &v1, const Vector4 &v2); static float Dot(const Vector4& v1, const Vector4& v2);
static Vector4 Min(const Vector4 &v1, const Vector4 &v2); static Vector4 Min(const Vector4& v1, const Vector4& v2);
static Vector4 Max(const Vector4 &v1, const Vector4 &v2); static Vector4 Max(const Vector4& v1, const Vector4& v2);
static Vector4 Min(); static Vector4 Min();
static Vector4 Max(); static Vector4 Max();
@@ -102,25 +105,26 @@ public:
static Vector4 Down(); static Vector4 Down();
static Vector4 Left(); static Vector4 Left();
static Vector4 Right(); static Vector4 Right();
static Vector4 Lerp(const Vector4 &v1, const Vector4 &v2, float d); static Vector4 Lerp(const Vector4& v1, const Vector4& v2, float d);
static Vector4 Slerp(const Vector4 &v1, const Vector4 &v2, float d); static Vector4 Slerp(const Vector4& v1, const Vector4& v2, float d);
static void OrthoNormalize(Vector4 &normal, Vector4 &tangent); // Gram-Schmidt Orthonormalization static void OrthoNormalize(Vector4& normal, Vector4& tangent); // Gram-Schmidt Orthonormalization
}; };
static_assert(std::is_pod<Vector4>::value, "kraken::Vector4 must be a POD type."); static_assert(std::is_pod<Vector4>::value, "kraken::Vector4 must be a POD type.");
} // namespace kraken } // namespace kraken
namespace std { namespace std {
template<> template<>
struct hash<kraken::Vector4> { struct hash<kraken::Vector4>
public: {
size_t operator()(const kraken::Vector4 &s) const public:
{ size_t operator()(const kraken::Vector4& s) const
size_t h1 = hash<float>()(s.x); {
size_t h2 = hash<float>()(s.y); size_t h1 = hash<float>()(s.x);
size_t h3 = hash<float>()(s.z); size_t h2 = hash<float>()(s.y);
size_t h4 = hash<float>()(s.w); size_t h3 = hash<float>()(s.z);
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3); size_t h4 = hash<float>()(s.w);
} return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
}; }
};
} // namespace std } // namespace std

View File

@@ -37,210 +37,210 @@ namespace kraken {
void AABB::init() void AABB::init()
{ {
min = Vector3::Min(); min = Vector3::Min();
max = Vector3::Max(); max = Vector3::Max();
} }
AABB AABB::Create() AABB AABB::Create()
{ {
AABB r; AABB r;
r.init(); r.init();
return r; return r;
} }
void AABB::init(const Vector3 &minPoint, const Vector3 &maxPoint) void AABB::init(const Vector3& minPoint, const Vector3& maxPoint)
{ {
min = minPoint; min = minPoint;
max = maxPoint; max = maxPoint;
} }
AABB AABB::Create(const Vector3 &minPoint, const Vector3 &maxPoint) AABB AABB::Create(const Vector3& minPoint, const Vector3& maxPoint)
{ {
AABB r; AABB r;
r.init(minPoint, maxPoint); r.init(minPoint, maxPoint);
return r; return r;
} }
void AABB::init(const Vector3 &corner1, const Vector3 &corner2, const Matrix4 &modelMatrix) void AABB::init(const Vector3& corner1, const Vector3& corner2, const Matrix4& modelMatrix)
{ {
for(int iCorner=0; iCorner<8; iCorner++) { for (int iCorner = 0; iCorner < 8; iCorner++) {
Vector3 sourceCornerVertex = Matrix4::DotWDiv(modelMatrix, Vector3::Create( Vector3 sourceCornerVertex = Matrix4::DotWDiv(modelMatrix, Vector3::Create(
(iCorner & 1) == 0 ? corner1.x : corner2.x, (iCorner & 1) == 0 ? corner1.x : corner2.x,
(iCorner & 2) == 0 ? corner1.y : corner2.y, (iCorner & 2) == 0 ? corner1.y : corner2.y,
(iCorner & 4) == 0 ? corner1.z : corner2.z)); (iCorner & 4) == 0 ? corner1.z : corner2.z));
if(iCorner == 0) { if (iCorner == 0) {
min = sourceCornerVertex; min = sourceCornerVertex;
max = sourceCornerVertex; max = sourceCornerVertex;
} else { } else {
if(sourceCornerVertex.x < min.x) min.x = sourceCornerVertex.x; if (sourceCornerVertex.x < min.x) min.x = sourceCornerVertex.x;
if(sourceCornerVertex.y < min.y) min.y = sourceCornerVertex.y; if (sourceCornerVertex.y < min.y) min.y = sourceCornerVertex.y;
if(sourceCornerVertex.z < min.z) min.z = sourceCornerVertex.z; if (sourceCornerVertex.z < min.z) min.z = sourceCornerVertex.z;
if(sourceCornerVertex.x > max.x) max.x = sourceCornerVertex.x; if (sourceCornerVertex.x > max.x) max.x = sourceCornerVertex.x;
if(sourceCornerVertex.y > max.y) max.y = sourceCornerVertex.y; if (sourceCornerVertex.y > max.y) max.y = sourceCornerVertex.y;
if(sourceCornerVertex.z > max.z) max.z = sourceCornerVertex.z; if (sourceCornerVertex.z > max.z) max.z = sourceCornerVertex.z;
}
} }
}
} }
AABB AABB::Create(const Vector3 &corner1, const Vector3 &corner2, const Matrix4 &modelMatrix) AABB AABB::Create(const Vector3& corner1, const Vector3& corner2, const Matrix4& modelMatrix)
{ {
AABB r; AABB r;
r.init(corner1, corner2, modelMatrix); r.init(corner1, corner2, modelMatrix);
return r; return r;
} }
bool AABB::operator ==(const AABB& b) const bool AABB::operator ==(const AABB& b) const
{ {
return min == b.min && max == b.max; return min == b.min && max == b.max;
} }
bool AABB::operator !=(const AABB& b) const bool AABB::operator !=(const AABB& b) const
{ {
return min != b.min || max != b.max; return min != b.min || max != b.max;
} }
Vector3 AABB::center() const Vector3 AABB::center() const
{ {
return (min + max) * 0.5f; return (min + max) * 0.5f;
} }
Vector3 AABB::size() const Vector3 AABB::size() const
{ {
return max - min; return max - min;
} }
float AABB::volume() const float AABB::volume() const
{ {
Vector3 s = size(); Vector3 s = size();
return s.x * s.y * s.z; return s.x * s.y * s.z;
} }
void AABB::scale(const Vector3 &s) void AABB::scale(const Vector3& s)
{ {
Vector3 prev_center = center(); Vector3 prev_center = center();
Vector3 prev_size = size(); Vector3 prev_size = size();
Vector3 new_scale = Vector3::Create(prev_size.x * s.x, Vector3 new_scale = Vector3::Create(prev_size.x * s.x,
prev_size.y * s.y, prev_size.y * s.y,
prev_size.z * s.z) * 0.5f; prev_size.z * s.z) * 0.5f;
min = prev_center - new_scale; min = prev_center - new_scale;
max = prev_center + new_scale; max = prev_center + new_scale;
} }
void AABB::scale(float s) void AABB::scale(float s)
{ {
scale(Vector3::Create(s)); scale(Vector3::Create(s));
} }
bool AABB::operator >(const AABB& b) const bool AABB::operator >(const AABB& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(min > b.min) { if (min > b.min) {
return true; return true;
} else if(min < b.min) { } else if (min < b.min) {
return false; return false;
} else if(max > b.max) { } else if (max > b.max) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool AABB::operator <(const AABB& b) const bool AABB::operator <(const AABB& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(min < b.min) { if (min < b.min) {
return true; return true;
} else if(min > b.min) { } else if (min > b.min) {
return false; return false;
} else if(max < b.max) { } else if (max < b.max) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool AABB::intersects(const AABB& b) const bool AABB::intersects(const AABB& b) const
{ {
// Return true if the two volumes intersect // Return true if the two volumes intersect
return min.x <= b.max.x && min.y <= b.max.y && min.z <= b.max.z && max.x >= b.min.x && max.y >= b.min.y && max.z >= b.min.z; return min.x <= b.max.x && min.y <= b.max.y && min.z <= b.max.z && max.x >= b.min.x && max.y >= b.min.y && max.z >= b.min.z;
} }
bool AABB::contains(const AABB &b) const bool AABB::contains(const AABB& b) const
{ {
// Return true if the passed KRAABB is entirely contained within this KRAABB // Return true if the passed KRAABB is entirely contained within this KRAABB
return b.min.x >= min.x && b.min.y >= min.y && b.min.z >= min.z && b.max.x <= max.x && b.max.y <= max.y && b.max.z <= max.z; return b.min.x >= min.x && b.min.y >= min.y && b.min.z >= min.z && b.max.x <= max.x && b.max.y <= max.y && b.max.z <= max.z;
} }
bool AABB::contains(const Vector3 &v) const bool AABB::contains(const Vector3& v) const
{ {
return v.x >= min.x && v.x <= max.x && v.y >= min.y && v.y <= max.y && v.z >= min.z && v.z <= max.z; return v.x >= min.x && v.x <= max.x && v.y >= min.y && v.y <= max.y && v.z >= min.z && v.z <= max.z;
} }
AABB AABB::Infinite() AABB AABB::Infinite()
{ {
return AABB::Create(Vector3::Min(), Vector3::Max()); return AABB::Create(Vector3::Min(), Vector3::Max());
} }
AABB AABB::Zero() AABB AABB::Zero()
{ {
return AABB::Create(Vector3::Zero(), Vector3::Zero()); return AABB::Create(Vector3::Zero(), Vector3::Zero());
} }
float AABB::longest_radius() const float AABB::longest_radius() const
{ {
float radius1 = (center() - min).magnitude(); float radius1 = (center() - min).magnitude();
float radius2 = (max - center()).magnitude(); float radius2 = (max - center()).magnitude();
return radius1 > radius2 ? radius1 : radius2; return radius1 > radius2 ? radius1 : radius2;
} }
bool AABB::intersectsLine(const Vector3 &v1, const Vector3 &v2) const bool AABB::intersectsLine(const Vector3& v1, const Vector3& v2) const
{ {
Vector3 dir = Vector3::Normalize(v2 - v1); Vector3 dir = Vector3::Normalize(v2 - v1);
float length = (v2 - v1).magnitude(); float length = (v2 - v1).magnitude();
// EZ cases: if the ray starts inside the box, or ends inside // EZ cases: if the ray starts inside the box, or ends inside
// the box, then it definitely hits the box. // the box, then it definitely hits the box.
// I'm using this code for ray tracing with an octree, // I'm using this code for ray tracing with an octree,
// so I needed rays that start and end within an // so I needed rays that start and end within an
// octree node to COUNT as hits. // octree node to COUNT as hits.
// You could modify this test to (ray starts inside and ends outside) // You could modify this test to (ray starts inside and ends outside)
// to qualify as a hit if you wanted to NOT count totally internal rays // to qualify as a hit if you wanted to NOT count totally internal rays
if( contains( v1 ) || contains( v2 ) ) if (contains(v1) || contains(v2))
return true ; return true;
// the algorithm says, find 3 t's, // the algorithm says, find 3 t's,
Vector3 t ; Vector3 t;
// LARGEST t is the only one we need to test if it's on the face. // LARGEST t is the only one we need to test if it's on the face.
for(int i = 0 ; i < 3 ; i++) { for (int i = 0; i < 3; i++) {
if( dir[i] > 0 ) { // CULL BACK FACE if (dir[i] > 0) { // CULL BACK FACE
t[i] = ( min[i] - v1[i] ) / dir[i]; t[i] = (min[i] - v1[i]) / dir[i];
} else { } else {
t[i] = ( max[i] - v1[i] ) / dir[i]; t[i] = (max[i] - v1[i]) / dir[i];
}
} }
}
int mi = 0;
if(t[1] > t[mi]) mi = 1; int mi = 0;
if(t[2] > t[mi]) mi = 2; if (t[1] > t[mi]) mi = 1;
if(t[mi] >= 0 && t[mi] <= length) { if (t[2] > t[mi]) mi = 2;
Vector3 pt = v1 + dir * t[mi]; if (t[mi] >= 0 && t[mi] <= length) {
Vector3 pt = v1 + dir * t[mi];
// check it's in the box in other 2 dimensions
int o1 = ( mi + 1 ) % 3 ; // i=0: o1=1, o2=2, i=1: o1=2,o2=0 etc. // check it's in the box in other 2 dimensions
int o2 = ( mi + 2 ) % 3 ; int o1 = (mi + 1) % 3; // i=0: o1=1, o2=2, i=1: o1=2,o2=0 etc.
int o2 = (mi + 2) % 3;
return pt[o1] >= min[o1] && pt[o1] <= max[o1] && pt[o2] >= min[o2] && pt[o2] <= max[o2];
} return pt[o1] >= min[o1] && pt[o1] <= max[o1] && pt[o2] >= min[o2] && pt[o2] <= max[o2];
}
return false ; // the ray did not hit the box.
return false; // the ray did not hit the box.
} }
bool AABB::intersectsRay(const Vector3 &v1, const Vector3 &dir) const bool AABB::intersectsRay(const Vector3& v1, const Vector3& dir) const
{ {
/* /*
Fast Ray-Box Intersection Fast Ray-Box Intersection
@@ -248,12 +248,13 @@ bool AABB::intersectsRay(const Vector3 &v1, const Vector3 &dir) const
from "Graphics Gems", Academic Press, 1990 from "Graphics Gems", Academic Press, 1990
*/ */
// FINDME, TODO - Perhaps there is a more efficient algorithm, as we don't actually need the exact coordinate of the intersection // FINDME, TODO - Perhaps there is a more efficient algorithm, as we don't actually need the exact coordinate of the intersection
enum { enum
RIGHT = 0, {
LEFT = 1, RIGHT = 0,
MIDDLE = 2 LEFT = 1,
MIDDLE = 2
} quadrant[3]; } quadrant[3];
bool inside = true; bool inside = true;
@@ -261,113 +262,113 @@ bool AABB::intersectsRay(const Vector3 &v1, const Vector3 &dir) const
maxT.init(); maxT.init();
Vector3 coord; Vector3 coord;
coord.init(); coord.init();
float candidatePlane[3]; float candidatePlane[3];
// Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view) // Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view)
for (int i=0; i<3; i++) for (int i = 0; i < 3; i++)
if(v1.c[i] < min.c[i]) { if (v1.c[i] < min.c[i]) {
quadrant[i] = LEFT; quadrant[i] = LEFT;
candidatePlane[i] = min.c[i]; candidatePlane[i] = min.c[i];
inside = false; inside = false;
} else if(v1.c[i] > max.c[i]) { } else if (v1.c[i] > max.c[i]) {
quadrant[i] = RIGHT; quadrant[i] = RIGHT;
candidatePlane[i] = max.c[i]; candidatePlane[i] = max.c[i];
inside = false; inside = false;
} else { } else {
quadrant[i] = MIDDLE; quadrant[i] = MIDDLE;
} }
/* Ray v1 inside bounding box */
if (inside) {
coord = v1;
return true;
}
/* Calculate T distances to candidate planes */ /* Ray v1 inside bounding box */
for (int i = 0; i < 3; i++) { if (inside) {
if (quadrant[i] != MIDDLE && dir[i] != 0.0f) { coord = v1;
maxT.c[i] = (candidatePlane[i]-v1.c[i]) / dir[i]; return true;
} else {
maxT.c[i] = -1.0f;
} }
}
/* Calculate T distances to candidate planes */
/* Get largest of the maxT's for final choice of intersection */ for (int i = 0; i < 3; i++) {
int whichPlane = 0; if (quadrant[i] != MIDDLE && dir[i] != 0.0f) {
for (int i = 1; i < 3; i++) { maxT.c[i] = (candidatePlane[i] - v1.c[i]) / dir[i];
if (maxT.c[whichPlane] < maxT.c[i]) { } else {
whichPlane = i; maxT.c[i] = -1.0f;
}
}
/* Check final candidate actually inside box */
if (maxT.c[whichPlane] < 0.0f) {
return false;
}
for (int i = 0; i < 3; i++) {
if (whichPlane != i) {
coord[i] = v1.c[i] + maxT.c[whichPlane] *dir[i];
if (coord[i] < min.c[i] || coord[i] > max.c[i]) {
return false;
} }
} else { }
assert(quadrant[i] != MIDDLE); // This should not be possible
coord[i] = candidatePlane[i]; /* Get largest of the maxT's for final choice of intersection */
} int whichPlane = 0;
for (int i = 1; i < 3; i++) {
if (maxT.c[whichPlane] < maxT.c[i]) {
whichPlane = i;
}
}
/* Check final candidate actually inside box */
if (maxT.c[whichPlane] < 0.0f) {
return false;
}
for (int i = 0; i < 3; i++) {
if (whichPlane != i) {
coord[i] = v1.c[i] + maxT.c[whichPlane] * dir[i];
if (coord[i] < min.c[i] || coord[i] > max.c[i]) {
return false;
}
} else {
assert(quadrant[i] != MIDDLE); // This should not be possible
coord[i] = candidatePlane[i];
}
}
return true; /* ray hits box */
}
bool AABB::intersectsSphere(const Vector3& center, float radius) const
{
// Arvo's Algorithm
float squaredDistance = 0;
// process X
if (center.x < min.x) {
float diff = center.x - min.x;
squaredDistance += diff * diff;
} else if (center.x > max.x) {
float diff = center.x - max.x;
squaredDistance += diff * diff;
} }
return true; /* ray hits box */
// process Y
if (center.y < min.y) {
float diff = center.y - min.y;
squaredDistance += diff * diff;
} else if (center.y > max.y) {
float diff = center.y - max.y;
squaredDistance += diff * diff;
}
// process Z
if (center.z < min.z) {
float diff = center.z - min.z;
squaredDistance += diff * diff;
} else if (center.z > max.z) {
float diff = center.z - max.z;
squaredDistance += diff * diff;
}
return squaredDistance <= radius;
} }
bool AABB::intersectsSphere(const Vector3 &center, float radius) const void AABB::encapsulate(const AABB& b)
{ {
// Arvo's Algorithm if (b.min.x < min.x) min.x = b.min.x;
if (b.min.y < min.y) min.y = b.min.y;
float squaredDistance = 0; if (b.min.z < min.z) min.z = b.min.z;
// process X if (b.max.x > max.x) max.x = b.max.x;
if (center.x < min.x) { if (b.max.y > max.y) max.y = b.max.y;
float diff = center.x - min.x; if (b.max.z > max.z) max.z = b.max.z;
squaredDistance += diff * diff;
} else if (center.x > max.x) {
float diff = center.x - max.x;
squaredDistance += diff * diff;
}
// process Y
if (center.y < min.y) {
float diff = center.y - min.y;
squaredDistance += diff * diff;
} else if (center.y > max.y) {
float diff = center.y - max.y;
squaredDistance += diff * diff;
}
// process Z
if (center.z < min.z) {
float diff = center.z - min.z;
squaredDistance += diff * diff;
} else if (center.z > max.z) {
float diff = center.z - max.z;
squaredDistance += diff * diff;
}
return squaredDistance <= radius;
} }
void AABB::encapsulate(const AABB & b) Vector3 AABB::nearestPoint(const Vector3& v) const
{ {
if(b.min.x < min.x) min.x = b.min.x; return Vector3::Create(KRCLAMP(v.x, min.x, max.x), KRCLAMP(v.y, min.y, max.y), KRCLAMP(v.z, min.z, max.z));
if(b.min.y < min.y) min.y = b.min.y;
if(b.min.z < min.z) min.z = b.min.z;
if(b.max.x > max.x) max.x = b.max.x;
if(b.max.y > max.y) max.y = b.max.y;
if(b.max.z > max.z) max.z = b.max.z;
}
Vector3 AABB::nearestPoint(const Vector3 & v) const
{
return Vector3::Create(KRCLAMP(v.x, min.x, max.x), KRCLAMP(v.y, min.y, max.y), KRCLAMP(v.z, min.z, max.z));
} }
} // namespace kraken } // namespace kraken

View File

@@ -35,26 +35,26 @@ namespace kraken {
HitInfo::HitInfo() HitInfo::HitInfo()
{ {
m_position = Vector3::Zero(); m_position = Vector3::Zero();
m_normal = Vector3::Zero(); m_normal = Vector3::Zero();
m_distance = 0.0f; m_distance = 0.0f;
m_node = NULL; m_node = NULL;
} }
HitInfo::HitInfo(const Vector3 &position, const Vector3 &normal, const float distance, KRNode *node) HitInfo::HitInfo(const Vector3& position, const Vector3& normal, const float distance, KRNode* node)
{ {
m_position = position; m_position = position;
m_normal = normal; m_normal = normal;
m_distance = distance; m_distance = distance;
m_node = node; m_node = node;
} }
HitInfo::HitInfo(const Vector3 &position, const Vector3 &normal, const float distance) HitInfo::HitInfo(const Vector3& position, const Vector3& normal, const float distance)
{ {
m_position = position; m_position = position;
m_normal = normal; m_normal = normal;
m_distance = distance; m_distance = distance;
m_node = NULL; m_node = NULL;
} }
HitInfo::~HitInfo() HitInfo::~HitInfo()
@@ -64,36 +64,36 @@ HitInfo::~HitInfo()
bool HitInfo::didHit() const bool HitInfo::didHit() const
{ {
return m_normal != Vector3::Zero(); return m_normal != Vector3::Zero();
} }
Vector3 HitInfo::getPosition() const Vector3 HitInfo::getPosition() const
{ {
return m_position; return m_position;
} }
Vector3 HitInfo::getNormal() const Vector3 HitInfo::getNormal() const
{ {
return m_normal; return m_normal;
} }
float HitInfo::getDistance() const float HitInfo::getDistance() const
{ {
return m_distance; return m_distance;
} }
KRNode *HitInfo::getNode() const KRNode* HitInfo::getNode() const
{ {
return m_node; return m_node;
} }
HitInfo& HitInfo::operator =(const HitInfo& b) HitInfo& HitInfo::operator =(const HitInfo& b)
{ {
m_position = b.m_position; m_position = b.m_position;
m_normal = b.m_normal; m_normal = b.m_normal;
m_distance = b.m_distance; m_distance = b.m_distance;
m_node = b.m_node; m_node = b.m_node;
return *this; return *this;
} }
} // namespace kraken } // namespace kraken

View File

@@ -35,171 +35,185 @@
namespace kraken { namespace kraken {
void Matrix2::init() { void Matrix2::init()
// Default constructor - Initialize with an identity matrix
static const float IDENTITY_MATRIX[] = {
1.0, 0.0,
0.0, 1.0
};
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 4);
}
void Matrix2::init(float *pMat) {
memcpy(c, pMat, sizeof(float) * 4);
}
void Matrix2::init(const Vector2 &new_axis_x, const Vector2 &new_axis_y)
{ {
c[0] = new_axis_x.x; c[1] = new_axis_x.y; // Default constructor - Initialize with an identity matrix
c[2] = new_axis_y.x; c[3] = new_axis_y.y; static const float IDENTITY_MATRIX[] = {
1.0, 0.0,
0.0, 1.0
};
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 4);
} }
void Matrix2::init(const Matrix2 &m) { void Matrix2::init(float* pMat)
memcpy(c, m.c, sizeof(float) * 4); {
memcpy(c, pMat, sizeof(float) * 4);
} }
float *Matrix2::getPointer() { void Matrix2::init(const Vector2& new_axis_x, const Vector2& new_axis_y)
return c; {
c[0] = new_axis_x.x; c[1] = new_axis_x.y;
c[2] = new_axis_y.x; c[3] = new_axis_y.y;
} }
float& Matrix2::operator[](unsigned i) { void Matrix2::init(const Matrix2& m)
return c[i]; {
memcpy(c, m.c, sizeof(float) * 4);
} }
float Matrix2::operator[](unsigned i) const { float* Matrix2::getPointer()
return c[i]; {
return c;
}
float& Matrix2::operator[](unsigned i)
{
return c[i];
}
float Matrix2::operator[](unsigned i) const
{
return c[i];
} }
// Overload comparison operator // Overload comparison operator
bool Matrix2::operator==(const Matrix2 &m) const { bool Matrix2::operator==(const Matrix2& m) const
return memcmp(c, m.c, sizeof(float) * 4) == 0; {
return memcmp(c, m.c, sizeof(float) * 4) == 0;
} }
// Overload compound multiply operator // Overload compound multiply operator
Matrix2& Matrix2::operator*=(const Matrix2 &m) { Matrix2& Matrix2::operator*=(const Matrix2& m)
float temp[4]; {
float temp[4];
int x,y;
int x, y;
for (x=0; x < 2; x++)
{ for (x = 0; x < 2; x++) {
for(y=0; y < 2; y++) for (y = 0; y < 2; y++) {
{ temp[y + (x * 2)] = (c[x * 2] * m.c[y]) +
temp[y + (x*2)] = (c[x*2] * m.c[y]) + (c[x * 2 + 1] * m.c[y + 2]);
(c[x*2+1] * m.c[y+2]);
}
} }
}
memcpy(c, temp, sizeof(float) * 4);
return *this; memcpy(c, temp, sizeof(float) * 4);
return *this;
} }
// Overload multiply operator // Overload multiply operator
Matrix2 Matrix2::operator*(const Matrix2 &m) const { Matrix2 Matrix2::operator*(const Matrix2& m) const
Matrix2 ret = *this; {
ret *= m; Matrix2 ret = *this;
return ret; ret *= m;
return ret;
} }
/* Rotate a matrix by an angle on a X, Y, or Z axis */ /* Rotate a matrix by an angle on a X, Y, or Z axis */
void Matrix2::rotate(float angle) { void Matrix2::rotate(float angle)
{
Matrix2 newMatrix; // Create new identity matrix
newMatrix.init(); Matrix2 newMatrix; // Create new identity matrix
newMatrix.c[0] = cosf(angle); newMatrix.init();
newMatrix.c[1] = -sinf(angle); newMatrix.c[0] = cosf(angle);
newMatrix.c[2] = -newMatrix.c[1]; newMatrix.c[1] = -sinf(angle);
newMatrix.c[3] = newMatrix.c[0]; newMatrix.c[2] = -newMatrix.c[1];
newMatrix.c[3] = newMatrix.c[0];
*this *= newMatrix;
*this *= newMatrix;
} }
/* Scale matrix by separate x, y, and z amounts */ /* Scale matrix by separate x, y, and z amounts */
void Matrix2::scale(float x, float y) { void Matrix2::scale(float x, float y)
Matrix2 newMatrix; // Create new identity matrix {
newMatrix.init(); Matrix2 newMatrix; // Create new identity matrix
newMatrix.init();
newMatrix.c[0] = x;
newMatrix.c[3] = y; newMatrix.c[0] = x;
newMatrix.c[3] = y;
*this *= newMatrix;
*this *= newMatrix;
} }
void Matrix2::scale(const Vector2 &v) { void Matrix2::scale(const Vector2& v)
scale(v.x, v.y); {
scale(v.x, v.y);
} }
/* Scale all dimensions equally */ /* Scale all dimensions equally */
void Matrix2::scale(float s) { void Matrix2::scale(float s)
scale(s,s); {
scale(s, s);
} }
/* Replace matrix with its inverse */ /* Replace matrix with its inverse */
bool Matrix2::invert() { bool Matrix2::invert()
float det = c[0] * c[3] - c[1] * c[2]; {
if (det == 0) { float det = c[0] * c[3] - c[1] * c[2];
return false; if (det == 0) {
} return false;
float invdet = 1.0f / det; }
float tmp = c[0]; float invdet = 1.0f / det;
c[0] = c[3] * invdet; float tmp = c[0];
c[1] = -c[1] * invdet; c[0] = c[3] * invdet;
c[2] = -c[2] * invdet; c[1] = -c[1] * invdet;
c[3] = tmp * invdet; c[2] = -c[2] * invdet;
c[3] = tmp * invdet;
return true;
return true;
} }
void Matrix2::transpose() { void Matrix2::transpose()
float tmp = c[1]; {
c[1] = c[2]; float tmp = c[1];
c[2] = tmp; c[1] = c[2];
c[2] = tmp;
} }
/* Dot Product, returning Vector2 */ /* Dot Product, returning Vector2 */
Vector2 Matrix2::Dot(const Matrix2 &m, const Vector2 &v) { Vector2 Matrix2::Dot(const Matrix2& m, const Vector2& v)
return Vector2::Create( {
v.c[0] * m.c[0] + v.c[1] * m.c[2], return Vector2::Create(
v.c[0] * m.c[1] + v.c[1] * m.c[3] v.c[0] * m.c[0] + v.c[1] * m.c[2],
); v.c[0] * m.c[1] + v.c[1] * m.c[3]
);
} }
Matrix2 Matrix2::Invert(const Matrix2 &m) Matrix2 Matrix2::Invert(const Matrix2& m)
{ {
Matrix2 matInvert = m; Matrix2 matInvert = m;
matInvert.invert(); matInvert.invert();
return matInvert; return matInvert;
} }
Matrix2 Matrix2::Transpose(const Matrix2 &m) Matrix2 Matrix2::Transpose(const Matrix2& m)
{ {
Matrix2 matTranspose = m; Matrix2 matTranspose = m;
matTranspose.transpose(); matTranspose.transpose();
return matTranspose; return matTranspose;
} }
Matrix2 Matrix2::Rotation(float angle) Matrix2 Matrix2::Rotation(float angle)
{ {
Matrix2 m; Matrix2 m;
m.init(); m.init();
m.rotate(angle); m.rotate(angle);
return m; return m;
} }
Matrix2 Matrix2::Scaling(const Vector2 &v) Matrix2 Matrix2::Scaling(const Vector2& v)
{ {
Matrix2 m; Matrix2 m;
m.init(); m.init();
m.scale(v); m.scale(v);
return m; return m;
} }
Matrix2 Matrix2::Identity() Matrix2 Matrix2::Identity()
{ {
Matrix2 m; Matrix2 m;
m.init(); m.init();
return m; return m;
} }
} // namespace kraken } // namespace kraken

View File

@@ -35,198 +35,214 @@
namespace kraken { namespace kraken {
void Matrix2x3::init() { void Matrix2x3::init()
// Default constructor - Initialize with an identity matrix
static const float IDENTITY_MATRIX[] = {
1.0, 0.0,
0.0, 1.0,
0.0, 0.0
};
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 6);
}
void Matrix2x3::init(float *pMat) {
memcpy(c, pMat, sizeof(float) * 6);
}
void Matrix2x3::init(const Vector2 &new_axis_x, const Vector2 &new_axis_y, const Vector2 &new_transform)
{ {
c[0] = new_axis_x.x; c[1] = new_axis_x.y; // Default constructor - Initialize with an identity matrix
c[2] = new_axis_y.x; c[3] = new_axis_y.y; static const float IDENTITY_MATRIX[] = {
c[4] = new_transform.x; c[5] = new_transform.y; 1.0, 0.0,
0.0, 1.0,
0.0, 0.0
};
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 6);
} }
void Matrix2x3::init(const Matrix2x3 &m) { void Matrix2x3::init(float* pMat)
memcpy(c, m.c, sizeof(float) * 6); {
memcpy(c, pMat, sizeof(float) * 6);
} }
float *Matrix2x3::getPointer() { void Matrix2x3::init(const Vector2& new_axis_x, const Vector2& new_axis_y, const Vector2& new_transform)
return c; {
c[0] = new_axis_x.x; c[1] = new_axis_x.y;
c[2] = new_axis_y.x; c[3] = new_axis_y.y;
c[4] = new_transform.x; c[5] = new_transform.y;
} }
float& Matrix2x3::operator[](unsigned i) { void Matrix2x3::init(const Matrix2x3& m)
return c[i]; {
memcpy(c, m.c, sizeof(float) * 6);
} }
float Matrix2x3::operator[](unsigned i) const { float* Matrix2x3::getPointer()
return c[i]; {
return c;
}
float& Matrix2x3::operator[](unsigned i)
{
return c[i];
}
float Matrix2x3::operator[](unsigned i) const
{
return c[i];
} }
// Overload comparison operator // Overload comparison operator
bool Matrix2x3::operator==(const Matrix2x3 &m) const { bool Matrix2x3::operator==(const Matrix2x3& m) const
return memcmp(c, m.c, sizeof(float) * 6) == 0; {
return memcmp(c, m.c, sizeof(float) * 6) == 0;
} }
// Overload compound multiply operator // Overload compound multiply operator
Matrix2x3& Matrix2x3::operator*=(const Matrix2x3 &m) { Matrix2x3& Matrix2x3::operator*=(const Matrix2x3& m)
float temp[6]; {
/* float temp[6];
temp[0] = c[0] * m[0] + c[2] * m[1]; /*
temp[1] = c[1] * m[0] + c[3] * m[1]; temp[0] = c[0] * m[0] + c[2] * m[1];
temp[2] = c[0] * m[2] + c[2] * m[3]; temp[1] = c[1] * m[0] + c[3] * m[1];
temp[3] = c[1] * m[2] + c[3] * m[3]; temp[2] = c[0] * m[2] + c[2] * m[3];
temp[4] = c[0] * m[4] + c[2] * m[5] + c[4]; temp[3] = c[1] * m[2] + c[3] * m[3];
temp[5] = c[1] * m[4] + c[3] * m[5] + c[5]; temp[4] = c[0] * m[4] + c[2] * m[5] + c[4];
*/ temp[5] = c[1] * m[4] + c[3] * m[5] + c[5];
temp[0] = m[0] * c[0] + m[2] * c[1]; */
temp[1] = m[1] * c[0] + m[3] * c[1]; temp[0] = m[0] * c[0] + m[2] * c[1];
temp[2] = m[0] * c[2] + m[2] * c[3]; temp[1] = m[1] * c[0] + m[3] * c[1];
temp[3] = m[1] * c[2] + m[3] * c[3]; temp[2] = m[0] * c[2] + m[2] * c[3];
temp[4] = m[0] * c[4] + m[2] * c[5] + m[4]; temp[3] = m[1] * c[2] + m[3] * c[3];
temp[5] = m[1] * c[4] + m[3] * c[5] + m[5]; temp[4] = m[0] * c[4] + m[2] * c[5] + m[4];
temp[5] = m[1] * c[4] + m[3] * c[5] + m[5];
memcpy(c, temp, sizeof(float) * 6); memcpy(c, temp, sizeof(float) * 6);
return *this; return *this;
} }
// Overload multiply operator // Overload multiply operator
Matrix2x3 Matrix2x3::operator*(const Matrix2x3 &m) const { Matrix2x3 Matrix2x3::operator*(const Matrix2x3& m) const
Matrix2x3 ret = *this; {
ret *= m; Matrix2x3 ret = *this;
return ret; ret *= m;
return ret;
} }
/* Perform translation operations on a matrix */ /* Perform translation operations on a matrix */
void Matrix2x3::translate(float x, float y) { void Matrix2x3::translate(float x, float y)
Matrix2x3 newMatrix; // Create new identity matrix {
newMatrix.init(); Matrix2x3 newMatrix; // Create new identity matrix
newMatrix.init();
newMatrix.transform.x = x;
newMatrix.transform.y = y; newMatrix.transform.x = x;
newMatrix.transform.y = y;
*this *= newMatrix;
*this *= newMatrix;
} }
void Matrix2x3::translate(const Vector2 &v) void Matrix2x3::translate(const Vector2& v)
{ {
translate(v.x, v.y); translate(v.x, v.y);
} }
/* Rotate a matrix by an angle on a X, Y, or Z axis */ /* Rotate a matrix by an angle on a X, Y, or Z axis */
void Matrix2x3::rotate(float angle) { void Matrix2x3::rotate(float angle)
Matrix2x3 newMatrix; {
newMatrix.init(); Matrix2x3 newMatrix;
newMatrix.c[0] = cosf(angle); newMatrix.init();
newMatrix.c[1] = -sinf(angle); newMatrix.c[0] = cosf(angle);
newMatrix.c[2] = -newMatrix.c[1]; newMatrix.c[1] = -sinf(angle);
newMatrix.c[3] = newMatrix.c[0]; newMatrix.c[2] = -newMatrix.c[1];
newMatrix.c[3] = newMatrix.c[0];
*this *= newMatrix;
*this *= newMatrix;
} }
/* Scale matrix by separate x, y, and z amounts */ /* Scale matrix by separate x, y, and z amounts */
void Matrix2x3::scale(float x, float y) { void Matrix2x3::scale(float x, float y)
Matrix2x3 newMatrix; // Create new identity matrix {
newMatrix.init(); Matrix2x3 newMatrix; // Create new identity matrix
newMatrix.init();
newMatrix.c[0] = x;
newMatrix.c[3] = y; newMatrix.c[0] = x;
newMatrix.c[3] = y;
*this *= newMatrix;
*this *= newMatrix;
} }
void Matrix2x3::scale(const Vector2 &v) { void Matrix2x3::scale(const Vector2& v)
scale(v.x, v.y); {
scale(v.x, v.y);
} }
/* Scale all dimensions equally */ /* Scale all dimensions equally */
void Matrix2x3::scale(float s) { void Matrix2x3::scale(float s)
scale(s,s); {
scale(s, s);
} }
/* Replace matrix with its inverse */ /* Replace matrix with its inverse */
bool Matrix2x3::invert() { bool Matrix2x3::invert()
float det = c[0] * c[3] - c[1] * c[2]; {
if (det == 0) { float det = c[0] * c[3] - c[1] * c[2];
return false; if (det == 0) {
} return false;
float invdet = 1.0f / det; }
float tmp[6]; float invdet = 1.0f / det;
tmp[0] = c[3] * invdet; float tmp[6];
tmp[1] = -c[1] * invdet; tmp[0] = c[3] * invdet;
tmp[2] = -c[2] * invdet; tmp[1] = -c[1] * invdet;
tmp[3] = c[0] * invdet; tmp[2] = -c[2] * invdet;
tmp[4] = (c[2] * c[5] - c[3] * c[4]) * invdet; tmp[3] = c[0] * invdet;
tmp[5] = (c[1] * c[4] - c[0] * c[5]) * invdet; tmp[4] = (c[2] * c[5] - c[3] * c[4]) * invdet;
memcpy(c, tmp, sizeof(float) * 6); tmp[5] = (c[1] * c[4] - c[0] * c[5]) * invdet;
memcpy(c, tmp, sizeof(float) * 6);
return true;
return true;
} }
/* Dot Product, returning Vector2 */ /* Dot Product, returning Vector2 */
Vector2 Matrix2x3::Dot(const Matrix2x3 &m, const Vector2 &v) { Vector2 Matrix2x3::Dot(const Matrix2x3& m, const Vector2& v)
return Vector2::Create( {
v.c[0] * m.c[0] + v.c[1] * m.c[2] + m.c[4], return Vector2::Create(
v.c[0] * m.c[1] + v.c[1] * m.c[3] + m.c[5] v.c[0] * m.c[0] + v.c[1] * m.c[2] + m.c[4],
); v.c[0] * m.c[1] + v.c[1] * m.c[3] + m.c[5]
);
} }
// Dot product without including translation; useful for transforming normals and tangents // Dot product without including translation; useful for transforming normals and tangents
Vector2 Matrix2x3::DotNoTranslate(const Matrix2x3 &m, const Vector2 &v) Vector2 Matrix2x3::DotNoTranslate(const Matrix2x3& m, const Vector2& v)
{ {
return Vector2::Create( return Vector2::Create(
v.c[0] * m.c[0] + v.c[1] * m.c[2], v.c[0] * m.c[0] + v.c[1] * m.c[2],
v.c[0] * m.c[1] + v.c[1] * m.c[3] v.c[0] * m.c[1] + v.c[1] * m.c[3]
); );
} }
Matrix2x3 Matrix2x3::Invert(const Matrix2x3 &m) Matrix2x3 Matrix2x3::Invert(const Matrix2x3& m)
{ {
Matrix2x3 matInvert = m; Matrix2x3 matInvert = m;
matInvert.invert(); matInvert.invert();
return matInvert; return matInvert;
} }
Matrix2x3 Matrix2x3::Translation(const Vector2 &v) Matrix2x3 Matrix2x3::Translation(const Vector2& v)
{ {
Matrix2x3 m; Matrix2x3 m;
m.init(); m.init();
m.transform.x = v.x; m.transform.x = v.x;
m.transform.y = v.y; m.transform.y = v.y;
return m; return m;
} }
Matrix2x3 Matrix2x3::Rotation(float angle) Matrix2x3 Matrix2x3::Rotation(float angle)
{ {
Matrix2x3 m; Matrix2x3 m;
m.init(); m.init();
m.rotate(angle); m.rotate(angle);
return m; return m;
} }
Matrix2x3 Matrix2x3::Scaling(const Vector2 &v) Matrix2x3 Matrix2x3::Scaling(const Vector2& v)
{ {
Matrix2x3 m; Matrix2x3 m;
m.init(); m.init();
m.scale(v); m.scale(v);
return m; return m;
} }
Matrix2x3 Matrix2x3::Identity() Matrix2x3 Matrix2x3::Identity()
{ {
Matrix2x3 m; Matrix2x3 m;
m.init(); m.init();
return m; return m;
} }
} // namespace kraken } // namespace kraken

View File

@@ -35,432 +35,453 @@
namespace kraken { namespace kraken {
void Matrix4::init() { void Matrix4::init()
// Default constructor - Initialize with an identity matrix
static const float IDENTITY_MATRIX[] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 16);
}
void Matrix4::init(float *pMat) {
memcpy(c, pMat, sizeof(float) * 16);
}
void Matrix4::init(const Vector3 &new_axis_x, const Vector3 &new_axis_y, const Vector3 &new_axis_z, const Vector3 &new_transform)
{ {
c[0] = new_axis_x.x; c[1] = new_axis_x.y; c[2] = new_axis_x.z; c[3] = 0.0f; // Default constructor - Initialize with an identity matrix
c[4] = new_axis_y.x; c[5] = new_axis_y.y; c[6] = new_axis_y.z; c[7] = 0.0f; static const float IDENTITY_MATRIX[] = {
c[8] = new_axis_z.x; c[9] = new_axis_z.y; c[10] = new_axis_z.z; c[11] = 0.0f; 1.0, 0.0, 0.0, 0.0,
c[12] = new_transform.x; c[13] = new_transform.y; c[14] = new_transform.z; c[15] = 1.0f; 0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 16);
} }
void Matrix4::init(const Matrix4 &m) { void Matrix4::init(float* pMat)
memcpy(c, m.c, sizeof(float) * 16); {
memcpy(c, pMat, sizeof(float) * 16);
} }
Matrix4 Matrix4::Create(float *pMat) void Matrix4::init(const Vector3& new_axis_x, const Vector3& new_axis_y, const Vector3& new_axis_z, const Vector3& new_transform)
{
c[0] = new_axis_x.x; c[1] = new_axis_x.y; c[2] = new_axis_x.z; c[3] = 0.0f;
c[4] = new_axis_y.x; c[5] = new_axis_y.y; c[6] = new_axis_y.z; c[7] = 0.0f;
c[8] = new_axis_z.x; c[9] = new_axis_z.y; c[10] = new_axis_z.z; c[11] = 0.0f;
c[12] = new_transform.x; c[13] = new_transform.y; c[14] = new_transform.z; c[15] = 1.0f;
}
void Matrix4::init(const Matrix4& m)
{
memcpy(c, m.c, sizeof(float) * 16);
}
Matrix4 Matrix4::Create(float* pMat)
{ {
Matrix4 r; Matrix4 r;
r.init(pMat); r.init(pMat);
return r; return r;
} }
Matrix4 Matrix4::Create(const Vector3 &new_axis_x, const Vector3 &new_axis_y, const Vector3 &new_axis_z, const Vector3 &new_transform) Matrix4 Matrix4::Create(const Vector3& new_axis_x, const Vector3& new_axis_y, const Vector3& new_axis_z, const Vector3& new_transform)
{ {
Matrix4 r; Matrix4 r;
r.init(new_axis_x, new_axis_y, new_axis_z, new_transform); r.init(new_axis_x, new_axis_y, new_axis_z, new_transform);
return r; return r;
} }
float *Matrix4::getPointer() { float* Matrix4::getPointer()
return c; {
return c;
} }
float& Matrix4::operator[](unsigned i) { float& Matrix4::operator[](unsigned i)
return c[i]; {
return c[i];
} }
float Matrix4::operator[](unsigned i) const { float Matrix4::operator[](unsigned i) const
return c[i]; {
return c[i];
} }
// Overload comparison operator // Overload comparison operator
bool Matrix4::operator==(const Matrix4 &m) const { bool Matrix4::operator==(const Matrix4& m) const
return memcmp(c, m.c, sizeof(float) * 16) == 0; {
return memcmp(c, m.c, sizeof(float) * 16) == 0;
} }
// Overload compound multiply operator // Overload compound multiply operator
Matrix4& Matrix4::operator*=(const Matrix4 &m) { Matrix4& Matrix4::operator*=(const Matrix4& m)
float temp[16]; {
float temp[16];
int x,y;
int x, y;
for (x=0; x < 4; x++)
{ for (x = 0; x < 4; x++) {
for(y=0; y < 4; y++) for (y = 0; y < 4; y++) {
{ temp[y + (x * 4)] = (c[x * 4] * m.c[y]) +
temp[y + (x*4)] = (c[x*4] * m.c[y]) + (c[(x * 4) + 1] * m.c[y + 4]) +
(c[(x*4)+1] * m.c[y+4]) + (c[(x * 4) + 2] * m.c[y + 8]) +
(c[(x*4)+2] * m.c[y+8]) + (c[(x * 4) + 3] * m.c[y + 12]);
(c[(x*4)+3] * m.c[y+12]);
}
} }
}
memcpy(c, temp, sizeof(float) << 4);
return *this; memcpy(c, temp, sizeof(float) << 4);
return *this;
} }
// Overload multiply operator // Overload multiply operator
Matrix4 Matrix4::operator*(const Matrix4 &m) const { Matrix4 Matrix4::operator*(const Matrix4& m) const
Matrix4 ret = *this; {
ret *= m; Matrix4 ret = *this;
return ret; ret *= m;
return ret;
} }
/* Generate a perspective view matrix using a field of view angle fov, /* Generate a perspective view matrix using a field of view angle fov,
* window aspect ratio, near and far clipping planes */ * window aspect ratio, near and far clipping planes */
void Matrix4::perspective(float fov, float aspect, float nearz, float farz) { void Matrix4::perspective(float fov, float aspect, float nearz, float farz)
{
memset(c, 0, sizeof(float) * 16);
memset(c, 0, sizeof(float) * 16);
float range= tanf(fov * 0.5f) * nearz;
c[0] = (2 * nearz) / ((range * aspect) - (-range * aspect)); float range = tanf(fov * 0.5f) * nearz;
c[5] = (2 * nearz) / (2 * range); c[0] = (2 * nearz) / ((range * aspect) - (-range * aspect));
c[10] = -(farz + nearz) / (farz - nearz); c[5] = (2 * nearz) / (2 * range);
c[11] = -1; c[10] = -(farz + nearz) / (farz - nearz);
c[14] = -(2 * farz * nearz) / (farz - nearz); c[11] = -1;
/* c[14] = -(2 * farz * nearz) / (farz - nearz);
float range= atan(fov / 20.0f) * nearz; /*
float r = range * aspect; float range= atan(fov / 20.0f) * nearz;
float t = range * 1.0; float r = range * aspect;
float t = range * 1.0;
c[0] = nearz / r;
c[5] = nearz / t; c[0] = nearz / r;
c[10] = -(farz + nearz) / (farz - nearz); c[5] = nearz / t;
c[11] = -(2.0 * farz * nearz) / (farz - nearz); c[10] = -(farz + nearz) / (farz - nearz);
c[14] = -1.0; c[11] = -(2.0 * farz * nearz) / (farz - nearz);
*/ c[14] = -1.0;
*/
} }
/* Perform translation operations on a matrix */ /* Perform translation operations on a matrix */
void Matrix4::translate(float x, float y, float z) { void Matrix4::translate(float x, float y, float z)
Matrix4 newMatrix; // Create new identity matrix {
newMatrix.init(); Matrix4 newMatrix; // Create new identity matrix
newMatrix.init();
newMatrix.c[12] = x;
newMatrix.c[13] = y; newMatrix.c[12] = x;
newMatrix.c[14] = z; newMatrix.c[13] = y;
newMatrix.c[14] = z;
*this *= newMatrix;
*this *= newMatrix;
} }
void Matrix4::translate(const Vector3 &v) void Matrix4::translate(const Vector3& v)
{ {
translate(v.x, v.y, v.z); translate(v.x, v.y, v.z);
} }
/* Rotate a matrix by an angle on a X, Y, or Z axis */ /* Rotate a matrix by an angle on a X, Y, or Z axis */
void Matrix4::rotate(float angle, AXIS axis) { void Matrix4::rotate(float angle, AXIS axis)
const int cos1[3] = { 5, 0, 0 }; // cos(angle) {
const int cos2[3] = { 10, 10, 5 }; // cos(angle) const int cos1[3] = { 5, 0, 0 }; // cos(angle)
const int sin1[3] = { 9, 2, 4 }; // -sin(angle) const int cos2[3] = { 10, 10, 5 }; // cos(angle)
const int sin2[3] = { 6, 8, 1 }; // sin(angle) const int sin1[3] = { 9, 2, 4 }; // -sin(angle)
const int sin2[3] = { 6, 8, 1 }; // sin(angle)
/*
X_AXIS: /*
X_AXIS:
1, 0, 0, 0
0, cos(angle), -sin(angle), 0 1, 0, 0, 0
0, sin(angle), cos(angle), 0 0, cos(angle), -sin(angle), 0
0, 0, 0, 1 0, sin(angle), cos(angle), 0
0, 0, 0, 1
Y_AXIS:
Y_AXIS:
cos(angle), 0, -sin(angle), 0
0, 1, 0, 0 cos(angle), 0, -sin(angle), 0
sin(angle), 0, cos(angle), 0 0, 1, 0, 0
0, 0, 0, 1 sin(angle), 0, cos(angle), 0
0, 0, 0, 1
Z_AXIS:
Z_AXIS:
cos(angle), -sin(angle), 0, 0
sin(angle), cos(angle), 0, 0 cos(angle), -sin(angle), 0, 0
0, 0, 1, 0 sin(angle), cos(angle), 0, 0
0, 0, 0, 1 0, 0, 1, 0
0, 0, 0, 1
*/
*/
Matrix4 newMatrix; // Create new identity matrix
newMatrix.init(); Matrix4 newMatrix; // Create new identity matrix
newMatrix.init();
uint8_t index = static_cast<uint8_t>(axis);
newMatrix.c[cos1[index]] = cosf(angle); uint8_t index = static_cast<uint8_t>(axis);
newMatrix.c[sin1[index]] = -sinf(angle); newMatrix.c[cos1[index]] = cosf(angle);
newMatrix.c[sin2[index]] = -newMatrix.c[sin1[index]]; newMatrix.c[sin1[index]] = -sinf(angle);
newMatrix.c[cos2[index]] = newMatrix.c[cos1[index]]; newMatrix.c[sin2[index]] = -newMatrix.c[sin1[index]];
newMatrix.c[cos2[index]] = newMatrix.c[cos1[index]];
*this *= newMatrix;
*this *= newMatrix;
} }
void Matrix4::rotate(const Quaternion &q) void Matrix4::rotate(const Quaternion& q)
{ {
*this *= q.rotationMatrix(); *this *= q.rotationMatrix();
} }
/* Scale matrix by separate x, y, and z amounts */ /* Scale matrix by separate x, y, and z amounts */
void Matrix4::scale(float x, float y, float z) { void Matrix4::scale(float x, float y, float z)
Matrix4 newMatrix; // Create new identity matrix {
newMatrix.init(); Matrix4 newMatrix; // Create new identity matrix
newMatrix.init();
newMatrix.c[0] = x;
newMatrix.c[5] = y; newMatrix.c[0] = x;
newMatrix.c[10] = z; newMatrix.c[5] = y;
newMatrix.c[10] = z;
*this *= newMatrix;
*this *= newMatrix;
} }
void Matrix4::scale(const Vector3 &v) { void Matrix4::scale(const Vector3& v)
scale(v.x, v.y, v.z); {
scale(v.x, v.y, v.z);
} }
/* Scale all dimensions equally */ /* Scale all dimensions equally */
void Matrix4::scale(float s) { void Matrix4::scale(float s)
scale(s,s,s); {
scale(s, s, s);
} }
// Initialize with a bias matrix // Initialize with a bias matrix
void Matrix4::bias() { void Matrix4::bias()
static const float BIAS_MATRIX[] = { {
0.5, 0.0, 0.0, 0.0, static const float BIAS_MATRIX[] = {
0.0, 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0, 0.0, 0.5, 0.0, 0.0,
0.5, 0.5, 0.5, 1.0 0.0, 0.0, 0.5, 0.0,
}; 0.5, 0.5, 0.5, 1.0
memcpy(c, BIAS_MATRIX, sizeof(float) * 16); };
memcpy(c, BIAS_MATRIX, sizeof(float) * 16);
} }
/* Generate an orthographic view matrix */ /* Generate an orthographic view matrix */
void Matrix4::ortho(float left, float right, float top, float bottom, float nearz, float farz) { void Matrix4::ortho(float left, float right, float top, float bottom, float nearz, float farz)
memset(c, 0, sizeof(float) * 16); {
c[0] = 2.0f / (right - left); memset(c, 0, sizeof(float) * 16);
c[5] = 2.0f / (bottom - top); c[0] = 2.0f / (right - left);
c[10] = -1.0f / (farz - nearz); c[5] = 2.0f / (bottom - top);
c[11] = -nearz / (farz - nearz); c[10] = -1.0f / (farz - nearz);
c[15] = 1.0f; c[11] = -nearz / (farz - nearz);
c[15] = 1.0f;
} }
/* Replace matrix with its inverse */ /* Replace matrix with its inverse */
bool Matrix4::invert() { bool Matrix4::invert()
// Based on gluInvertMatrix implementation {
// Based on gluInvertMatrix implementation
float inv[16], det;
int i; float inv[16], det;
int i;
inv[0] = c[5]*c[10]*c[15] - c[5]*c[11]*c[14] - c[9]*c[6]*c[15]
+ c[9]*c[7]*c[14] + c[13]*c[6]*c[11] - c[13]*c[7]*c[10]; inv[0] = c[5] * c[10] * c[15] - c[5] * c[11] * c[14] - c[9] * c[6] * c[15]
inv[4] = -c[4]*c[10]*c[15] + c[4]*c[11]*c[14] + c[8]*c[6]*c[15] + c[9] * c[7] * c[14] + c[13] * c[6] * c[11] - c[13] * c[7] * c[10];
- c[8]*c[7]*c[14] - c[12]*c[6]*c[11] + c[12]*c[7]*c[10]; inv[4] = -c[4] * c[10] * c[15] + c[4] * c[11] * c[14] + c[8] * c[6] * c[15]
inv[8] = c[4]*c[9]*c[15] - c[4]*c[11]*c[13] - c[8]*c[5]*c[15] - c[8] * c[7] * c[14] - c[12] * c[6] * c[11] + c[12] * c[7] * c[10];
+ c[8]*c[7]*c[13] + c[12]*c[5]*c[11] - c[12]*c[7]*c[9]; inv[8] = c[4] * c[9] * c[15] - c[4] * c[11] * c[13] - c[8] * c[5] * c[15]
inv[12] = -c[4]*c[9]*c[14] + c[4]*c[10]*c[13] + c[8]*c[5]*c[14] + c[8] * c[7] * c[13] + c[12] * c[5] * c[11] - c[12] * c[7] * c[9];
- c[8]*c[6]*c[13] - c[12]*c[5]*c[10] + c[12]*c[6]*c[9]; inv[12] = -c[4] * c[9] * c[14] + c[4] * c[10] * c[13] + c[8] * c[5] * c[14]
inv[1] = -c[1]*c[10]*c[15] + c[1]*c[11]*c[14] + c[9]*c[2]*c[15] - c[8] * c[6] * c[13] - c[12] * c[5] * c[10] + c[12] * c[6] * c[9];
- c[9]*c[3]*c[14] - c[13]*c[2]*c[11] + c[13]*c[3]*c[10]; inv[1] = -c[1] * c[10] * c[15] + c[1] * c[11] * c[14] + c[9] * c[2] * c[15]
inv[5] = c[0]*c[10]*c[15] - c[0]*c[11]*c[14] - c[8]*c[2]*c[15] - c[9] * c[3] * c[14] - c[13] * c[2] * c[11] + c[13] * c[3] * c[10];
+ c[8]*c[3]*c[14] + c[12]*c[2]*c[11] - c[12]*c[3]*c[10]; inv[5] = c[0] * c[10] * c[15] - c[0] * c[11] * c[14] - c[8] * c[2] * c[15]
inv[9] = -c[0]*c[9]*c[15] + c[0]*c[11]*c[13] + c[8]*c[1]*c[15] + c[8] * c[3] * c[14] + c[12] * c[2] * c[11] - c[12] * c[3] * c[10];
- c[8]*c[3]*c[13] - c[12]*c[1]*c[11] + c[12]*c[3]*c[9]; inv[9] = -c[0] * c[9] * c[15] + c[0] * c[11] * c[13] + c[8] * c[1] * c[15]
inv[13] = c[0]*c[9]*c[14] - c[0]*c[10]*c[13] - c[8]*c[1]*c[14] - c[8] * c[3] * c[13] - c[12] * c[1] * c[11] + c[12] * c[3] * c[9];
+ c[8]*c[2]*c[13] + c[12]*c[1]*c[10] - c[12]*c[2]*c[9]; inv[13] = c[0] * c[9] * c[14] - c[0] * c[10] * c[13] - c[8] * c[1] * c[14]
inv[2] = c[1]*c[6]*c[15] - c[1]*c[7]*c[14] - c[5]*c[2]*c[15] + c[8] * c[2] * c[13] + c[12] * c[1] * c[10] - c[12] * c[2] * c[9];
+ c[5]*c[3]*c[14] + c[13]*c[2]*c[7] - c[13]*c[3]*c[6]; inv[2] = c[1] * c[6] * c[15] - c[1] * c[7] * c[14] - c[5] * c[2] * c[15]
inv[6] = -c[0]*c[6]*c[15] + c[0]*c[7]*c[14] + c[4]*c[2]*c[15] + c[5] * c[3] * c[14] + c[13] * c[2] * c[7] - c[13] * c[3] * c[6];
- c[4]*c[3]*c[14] - c[12]*c[2]*c[7] + c[12]*c[3]*c[6]; inv[6] = -c[0] * c[6] * c[15] + c[0] * c[7] * c[14] + c[4] * c[2] * c[15]
inv[10] = c[0]*c[5]*c[15] - c[0]*c[7]*c[13] - c[4]*c[1]*c[15] - c[4] * c[3] * c[14] - c[12] * c[2] * c[7] + c[12] * c[3] * c[6];
+ c[4]*c[3]*c[13] + c[12]*c[1]*c[7] - c[12]*c[3]*c[5]; inv[10] = c[0] * c[5] * c[15] - c[0] * c[7] * c[13] - c[4] * c[1] * c[15]
inv[14] = -c[0]*c[5]*c[14] + c[0]*c[6]*c[13] + c[4]*c[1]*c[14] + c[4] * c[3] * c[13] + c[12] * c[1] * c[7] - c[12] * c[3] * c[5];
- c[4]*c[2]*c[13] - c[12]*c[1]*c[6] + c[12]*c[2]*c[5]; inv[14] = -c[0] * c[5] * c[14] + c[0] * c[6] * c[13] + c[4] * c[1] * c[14]
inv[3] = -c[1]*c[6]*c[11] + c[1]*c[7]*c[10] + c[5]*c[2]*c[11] - c[4] * c[2] * c[13] - c[12] * c[1] * c[6] + c[12] * c[2] * c[5];
- c[5]*c[3]*c[10] - c[9]*c[2]*c[7] + c[9]*c[3]*c[6]; inv[3] = -c[1] * c[6] * c[11] + c[1] * c[7] * c[10] + c[5] * c[2] * c[11]
inv[7] = c[0]*c[6]*c[11] - c[0]*c[7]*c[10] - c[4]*c[2]*c[11] - c[5] * c[3] * c[10] - c[9] * c[2] * c[7] + c[9] * c[3] * c[6];
+ c[4]*c[3]*c[10] + c[8]*c[2]*c[7] - c[8]*c[3]*c[6]; inv[7] = c[0] * c[6] * c[11] - c[0] * c[7] * c[10] - c[4] * c[2] * c[11]
inv[11] = -c[0]*c[5]*c[11] + c[0]*c[7]*c[9] + c[4]*c[1]*c[11] + c[4] * c[3] * c[10] + c[8] * c[2] * c[7] - c[8] * c[3] * c[6];
- c[4]*c[3]*c[9] - c[8]*c[1]*c[7] + c[8]*c[3]*c[5]; inv[11] = -c[0] * c[5] * c[11] + c[0] * c[7] * c[9] + c[4] * c[1] * c[11]
inv[15] = c[0]*c[5]*c[10] - c[0]*c[6]*c[9] - c[4]*c[1]*c[10] - c[4] * c[3] * c[9] - c[8] * c[1] * c[7] + c[8] * c[3] * c[5];
+ c[4]*c[2]*c[9] + c[8]*c[1]*c[6] - c[8]*c[2]*c[5]; inv[15] = c[0] * c[5] * c[10] - c[0] * c[6] * c[9] - c[4] * c[1] * c[10]
+ c[4] * c[2] * c[9] + c[8] * c[1] * c[6] - c[8] * c[2] * c[5];
det = c[0]*inv[0] + c[1]*inv[4] + c[2]*inv[8] + c[3]*inv[12];
det = c[0] * inv[0] + c[1] * inv[4] + c[2] * inv[8] + c[3] * inv[12];
if (det == 0) {
return false; if (det == 0) {
} return false;
}
det = 1.0f / det;
det = 1.0f / det;
for (i = 0; i < 16; i++) {
c[i] = inv[i] * det; for (i = 0; i < 16; i++) {
} c[i] = inv[i] * det;
}
return true;
return true;
} }
void Matrix4::transpose() { void Matrix4::transpose()
float trans[16]; {
for(int x=0; x<4; x++) { float trans[16];
for(int y=0; y<4; y++) { for (int x = 0; x < 4; x++) {
trans[x + y * 4] = c[y + x * 4]; for (int y = 0; y < 4; y++) {
} trans[x + y * 4] = c[y + x * 4];
} }
memcpy(c, trans, sizeof(float) * 16); }
memcpy(c, trans, sizeof(float) * 16);
} }
/* Dot Product, returning Vector3 */ /* Dot Product, returning Vector3 */
Vector3 Matrix4::Dot(const Matrix4 &m, const Vector3 &v) { Vector3 Matrix4::Dot(const Matrix4& m, const Vector3& v)
return Vector3::Create( {
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12], return Vector3::Create(
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13], v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14] v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
); v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14]
);
} }
Vector4 Matrix4::Dot4(const Matrix4 &m, const Vector4 &v) { Vector4 Matrix4::Dot4(const Matrix4& m, const Vector4& v)
{
#ifdef KRAKEN_USE_ARM_NEON #ifdef KRAKEN_USE_ARM_NEON
Vector4 d; Vector4 d;
d.init(); d.init();
asm volatile ( asm volatile (
"vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v "vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v
"vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m "vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m
"vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4 "vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4
"vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8 "vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8
"vld1.32 {d24, d25}, [%0]! \n\t" //Q4 = m+12 "vld1.32 {d24, d25}, [%0]! \n\t" //Q4 = m+12
"vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0] "vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0]
"vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1] "vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1]
"vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2] "vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2]
"vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3] "vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3]
"vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12 "vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12
: /* no output registers */ : /* no output registers */
: "r"(m.c), "r"(v.c), "r"(d.c) : "r"(m.c), "r"(v.c), "r"(d.c)
: "q0", "q9", "q10","q11", "q12", "q13", "memory" : "q0", "q9", "q10", "q11", "q12", "q13", "memory"
);
return d;
#else
return Vector4::Create(
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14],
v.c[0] * m.c[3] + v.c[1] * m.c[7] + v.c[2] * m.c[11] + m.c[15]
); );
return d;
#else
return Vector4::Create(
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14],
v.c[0] * m.c[3] + v.c[1] * m.c[7] + v.c[2] * m.c[11] + m.c[15]
);
#endif #endif
} }
// Dot product without including translation; useful for transforming normals and tangents // Dot product without including translation; useful for transforming normals and tangents
Vector3 Matrix4::DotNoTranslate(const Matrix4 &m, const Vector3 &v) Vector3 Matrix4::DotNoTranslate(const Matrix4& m, const Vector3& v)
{ {
return Vector3::Create( return Vector3::Create(
v.x * m.c[0] + v.y * m.c[4] + v.z * m.c[8], v.x * m.c[0] + v.y * m.c[4] + v.z * m.c[8],
v.x * m.c[1] + v.y * m.c[5] + v.z * m.c[9], v.x * m.c[1] + v.y * m.c[5] + v.z * m.c[9],
v.x * m.c[2] + v.y * m.c[6] + v.z * m.c[10] v.x * m.c[2] + v.y * m.c[6] + v.z * m.c[10]
); );
} }
/* Dot Product, returning w component as if it were a Vector4 (This will be deprecated once Vector4 is implemented instead*/ /* Dot Product, returning w component as if it were a Vector4 (This will be deprecated once Vector4 is implemented instead*/
float Matrix4::DotW(const Matrix4 &m, const Vector3 &v) { float Matrix4::DotW(const Matrix4& m, const Vector3& v)
return v.x * m.c[0*4 + 3] + v.y * m.c[1*4 + 3] + v.z * m.c[2*4 + 3] + m.c[3*4 + 3]; {
return v.x * m.c[0 * 4 + 3] + v.y * m.c[1 * 4 + 3] + v.z * m.c[2 * 4 + 3] + m.c[3 * 4 + 3];
} }
/* Dot Product followed by W-divide */ /* Dot Product followed by W-divide */
Vector3 Matrix4::DotWDiv(const Matrix4 &m, const Vector3 &v) { Vector3 Matrix4::DotWDiv(const Matrix4& m, const Vector3& v)
Vector4 r = Dot4(m, Vector4::Create(v, 1.0f)); {
return Vector3::Create(r) / r.w; Vector4 r = Dot4(m, Vector4::Create(v, 1.0f));
return Vector3::Create(r) / r.w;
} }
Matrix4 Matrix4::LookAt(const Vector3 &cameraPos, const Vector3 &lookAtPos, const Vector3 &upDirection) Matrix4 Matrix4::LookAt(const Vector3& cameraPos, const Vector3& lookAtPos, const Vector3& upDirection)
{ {
Matrix4 matLookat; Matrix4 matLookat;
matLookat.init(); matLookat.init();
Vector3 lookat_z_axis = lookAtPos - cameraPos; Vector3 lookat_z_axis = lookAtPos - cameraPos;
lookat_z_axis.normalize(); lookat_z_axis.normalize();
Vector3 lookat_x_axis = Vector3::Cross(upDirection, lookat_z_axis); Vector3 lookat_x_axis = Vector3::Cross(upDirection, lookat_z_axis);
lookat_x_axis.normalize(); lookat_x_axis.normalize();
Vector3 lookat_y_axis = Vector3::Cross(lookat_z_axis, lookat_x_axis); Vector3 lookat_y_axis = Vector3::Cross(lookat_z_axis, lookat_x_axis);
matLookat.getPointer()[0] = lookat_x_axis.x; matLookat.getPointer()[0] = lookat_x_axis.x;
matLookat.getPointer()[1] = lookat_y_axis.x; matLookat.getPointer()[1] = lookat_y_axis.x;
matLookat.getPointer()[2] = lookat_z_axis.x; matLookat.getPointer()[2] = lookat_z_axis.x;
matLookat.getPointer()[4] = lookat_x_axis.y; matLookat.getPointer()[4] = lookat_x_axis.y;
matLookat.getPointer()[5] = lookat_y_axis.y; matLookat.getPointer()[5] = lookat_y_axis.y;
matLookat.getPointer()[6] = lookat_z_axis.y; matLookat.getPointer()[6] = lookat_z_axis.y;
matLookat.getPointer()[8] = lookat_x_axis.z; matLookat.getPointer()[8] = lookat_x_axis.z;
matLookat.getPointer()[9] = lookat_y_axis.z; matLookat.getPointer()[9] = lookat_y_axis.z;
matLookat.getPointer()[10] = lookat_z_axis.z; matLookat.getPointer()[10] = lookat_z_axis.z;
matLookat.getPointer()[12] = -Vector3::Dot(lookat_x_axis, cameraPos); matLookat.getPointer()[12] = -Vector3::Dot(lookat_x_axis, cameraPos);
matLookat.getPointer()[13] = -Vector3::Dot(lookat_y_axis, cameraPos); matLookat.getPointer()[13] = -Vector3::Dot(lookat_y_axis, cameraPos);
matLookat.getPointer()[14] = -Vector3::Dot(lookat_z_axis, cameraPos); matLookat.getPointer()[14] = -Vector3::Dot(lookat_z_axis, cameraPos);
return matLookat; return matLookat;
} }
Matrix4 Matrix4::Invert(const Matrix4 &m) Matrix4 Matrix4::Invert(const Matrix4& m)
{ {
Matrix4 matInvert = m; Matrix4 matInvert = m;
matInvert.invert(); matInvert.invert();
return matInvert; return matInvert;
} }
Matrix4 Matrix4::Transpose(const Matrix4 &m) Matrix4 Matrix4::Transpose(const Matrix4& m)
{ {
Matrix4 matTranspose = m; Matrix4 matTranspose = m;
matTranspose.transpose(); matTranspose.transpose();
return matTranspose; return matTranspose;
} }
Matrix4 Matrix4::Translation(const Vector3 &v) Matrix4 Matrix4::Translation(const Vector3& v)
{ {
Matrix4 m; Matrix4 m;
m.init(); m.init();
m[12] = v.x; m[12] = v.x;
m[13] = v.y; m[13] = v.y;
m[14] = v.z; m[14] = v.z;
// m.translate(v); // m.translate(v);
return m; return m;
} }
Matrix4 Matrix4::Rotation(const Vector3 &v) Matrix4 Matrix4::Rotation(const Vector3& v)
{ {
Matrix4 m; Matrix4 m;
m.init(); m.init();
m.rotate(v.x, AXIS::X_AXIS); m.rotate(v.x, AXIS::X_AXIS);
m.rotate(v.y, AXIS::Y_AXIS); m.rotate(v.y, AXIS::Y_AXIS);
m.rotate(v.z, AXIS::Z_AXIS); m.rotate(v.z, AXIS::Z_AXIS);
return m; return m;
} }
Matrix4 Matrix4::Scaling(const Vector3 &v) Matrix4 Matrix4::Scaling(const Vector3& v)
{ {
Matrix4 m; Matrix4 m;
m.init(); m.init();
m.scale(v); m.scale(v);
return m; return m;
} }
Matrix4 Matrix4::Identity() Matrix4 Matrix4::Identity()
{ {
Matrix4 m; Matrix4 m;
m.init(); m.init();
return m; return m;
} }
} // namespace kraken } // namespace kraken

View File

@@ -35,323 +35,353 @@
namespace kraken { namespace kraken {
void Quaternion::init() { void Quaternion::init()
c[0] = 1.0; {
c[1] = 0.0; c[0] = 1.0;
c[2] = 0.0; c[1] = 0.0;
c[3] = 0.0; c[2] = 0.0;
c[3] = 0.0;
} }
Quaternion Quaternion::Create() Quaternion Quaternion::Create()
{ {
Quaternion r; Quaternion r;
r.init(); r.init();
return r; return r;
} }
void Quaternion::init(float w, float x, float y, float z) { void Quaternion::init(float w, float x, float y, float z)
c[0] = w; {
c[1] = x; c[0] = w;
c[2] = y; c[1] = x;
c[3] = z; c[2] = y;
c[3] = z;
} }
Quaternion Quaternion::Create(float w, float x, float y, float z) Quaternion Quaternion::Create(float w, float x, float y, float z)
{ {
Quaternion r; Quaternion r;
r.init(w, x, y, z); r.init(w, x, y, z);
return r; return r;
} }
void Quaternion::init(const Quaternion& p) { void Quaternion::init(const Quaternion& p)
c[0] = p[0]; {
c[1] = p[1]; c[0] = p[0];
c[2] = p[2]; c[1] = p[1];
c[3] = p[3]; c[2] = p[2];
c[3] = p[3];
} }
Quaternion Quaternion::Create(const Quaternion& p) Quaternion Quaternion::Create(const Quaternion& p)
{ {
Quaternion r; Quaternion r;
r.init(p); r.init(p);
return r; return r;
} }
void Quaternion::init(const Vector3 &euler) { void Quaternion::init(const Vector3& euler)
setEulerZYX(euler);
}
Quaternion Quaternion::Create(const Vector3 &euler)
{ {
Quaternion r; setEulerZYX(euler);
r.init(euler);
return r;
} }
void Quaternion::init(const Vector3 &from_vector, const Vector3 &to_vector) { Quaternion Quaternion::Create(const Vector3& euler)
Vector3 a = Vector3::Cross(from_vector, to_vector);
c[0] = a[0];
c[1] = a[1];
c[2] = a[2];
c[3] = sqrtf(from_vector.sqrMagnitude() * to_vector.sqrMagnitude()) + Vector3::Dot(from_vector, to_vector);
normalize();
}
Quaternion Quaternion::Create(const Vector3 &from_vector, const Vector3 &to_vector)
{ {
Quaternion r; Quaternion r;
r.init(from_vector, to_vector); r.init(euler);
return r; return r;
} }
void Quaternion::setEulerXYZ(const Vector3 &euler) void Quaternion::init(const Vector3& from_vector, const Vector3& to_vector)
{ {
*this = Quaternion::FromAngleAxis(Vector3::Create(1.0f, 0.0f, 0.0f), euler.x)
* Quaternion::FromAngleAxis(Vector3::Create(0.0f, 1.0f, 0.0f), euler.y) Vector3 a = Vector3::Cross(from_vector, to_vector);
* Quaternion::FromAngleAxis(Vector3::Create(0.0f, 0.0f, 1.0f), euler.z); c[0] = a[0];
c[1] = a[1];
c[2] = a[2];
c[3] = sqrtf(from_vector.sqrMagnitude() * to_vector.sqrMagnitude()) + Vector3::Dot(from_vector, to_vector);
normalize();
} }
void Quaternion::setEulerZYX(const Vector3 &euler) { Quaternion Quaternion::Create(const Vector3& from_vector, const Vector3& to_vector)
// ZYX Order! {
float c1 = cosf(euler[0] * 0.5f); Quaternion r;
float c2 = cosf(euler[1] * 0.5f); r.init(from_vector, to_vector);
float c3 = cosf(euler[2] * 0.5f); return r;
float s1 = sinf(euler[0] * 0.5f);
float s2 = sinf(euler[1] * 0.5f);
float s3 = sinf(euler[2] * 0.5f);
c[0] = c1 * c2 * c3 + s1 * s2 * s3;
c[1] = s1 * c2 * c3 - c1 * s2 * s3;
c[2] = c1 * s2 * c3 + s1 * c2 * s3;
c[3] = c1 * c2 * s3 - s1 * s2 * c3;
} }
float Quaternion::operator [](unsigned i) const { void Quaternion::setEulerXYZ(const Vector3& euler)
return c[i]; {
*this = Quaternion::FromAngleAxis(Vector3::Create(1.0f, 0.0f, 0.0f), euler.x)
* Quaternion::FromAngleAxis(Vector3::Create(0.0f, 1.0f, 0.0f), euler.y)
* Quaternion::FromAngleAxis(Vector3::Create(0.0f, 0.0f, 1.0f), euler.z);
} }
float &Quaternion::operator [](unsigned i) { void Quaternion::setEulerZYX(const Vector3& euler)
return c[i]; {
// ZYX Order!
float c1 = cosf(euler[0] * 0.5f);
float c2 = cosf(euler[1] * 0.5f);
float c3 = cosf(euler[2] * 0.5f);
float s1 = sinf(euler[0] * 0.5f);
float s2 = sinf(euler[1] * 0.5f);
float s3 = sinf(euler[2] * 0.5f);
c[0] = c1 * c2 * c3 + s1 * s2 * s3;
c[1] = s1 * c2 * c3 - c1 * s2 * s3;
c[2] = c1 * s2 * c3 + s1 * c2 * s3;
c[3] = c1 * c2 * s3 - s1 * s2 * c3;
} }
Vector3 Quaternion::eulerXYZ() const { float Quaternion::operator [](unsigned i) const
float a2 = 2 * (c[0] * c[2] - c[1] * c[3]); {
if(a2 <= -0.99999) { return c[i];
return Vector3::Create(
2.0f * atan2f(c[1], c[0]),
-PI * 0.5f,
0
);
} else if(a2 >= 0.99999) {
return Vector3::Create(
2.0f * atan2f(c[1], c[0]),
PI * 0.5f,
0
);
} else {
return Vector3::Create(
atan2f(2 * (c[0] * c[1] + c[2] * c[3]), (1 - 2 * (c[1] * c[1] + c[2] * c[2]))),
asinf(a2),
atan2f(2 * (c[0] * c[3] + c[1] * c[2]), (1 - 2 * (c[2] * c[2] + c[3] * c[3])))
);
}
} }
bool operator ==(Quaternion &v1, Quaternion &v2) { float& Quaternion::operator [](unsigned i)
return {
v1[0] == v2[0] return c[i];
&& v1[1] == v2[1]
&& v1[2] == v2[2]
&& v1[3] == v2[3];
} }
bool operator !=(Quaternion &v1, Quaternion &v2) { Vector3 Quaternion::eulerXYZ() const
return {
v1[0] != v2[0] float a2 = 2 * (c[0] * c[2] - c[1] * c[3]);
|| v1[1] != v2[1] if (a2 <= -0.99999) {
|| v1[2] != v2[2] return Vector3::Create(
|| v1[3] != v2[3]; 2.0f * atan2f(c[1], c[0]),
} -PI * 0.5f,
0
Quaternion Quaternion::operator *(const Quaternion &v) {
float t0 = (c[3]-c[2])*(v[2]-v[3]);
float t1 = (c[0]+c[1])*(v[0]+v[1]);
float t2 = (c[0]-c[1])*(v[2]+v[3]);
float t3 = (c[3]+c[2])*(v[0]-v[1]);
float t4 = (c[3]-c[1])*(v[1]-v[2]);
float t5 = (c[3]+c[1])*(v[1]+v[2]);
float t6 = (c[0]+c[2])*(v[0]-v[3]);
float t7 = (c[0]-c[2])*(v[0]+v[3]);
float t8 = t5+t6+t7;
float t9 = (t4+t8)/2;
return Quaternion::Create(
t0+t9-t5,
t1+t9-t8,
t2+t9-t7,
t3+t9-t6
); );
} } else if (a2 >= 0.99999) {
return Vector3::Create(
Quaternion Quaternion::operator *(float v) const { 2.0f * atan2f(c[1], c[0]),
return Quaternion::Create(c[0] * v, c[1] * v, c[2] * v, c[3] * v); PI * 0.5f,
} 0
Quaternion Quaternion::operator /(float num) const {
float inv_num = 1.0f / num;
return Quaternion::Create(c[0] * inv_num, c[1] * inv_num, c[2] * inv_num, c[3] * inv_num);
}
Quaternion Quaternion::operator +(const Quaternion &v) const {
return Quaternion::Create(c[0] + v[0], c[1] + v[1], c[2] + v[2], c[3] + v[3]);
}
Quaternion Quaternion::operator -(const Quaternion &v) const {
return Quaternion::Create(c[0] - v[0], c[1] - v[1], c[2] - v[2], c[3] - v[3]);
}
Quaternion& Quaternion::operator +=(const Quaternion& v) {
c[0] += v[0];
c[1] += v[1];
c[2] += v[2];
c[3] += v[3];
return *this;
}
Quaternion& Quaternion::operator -=(const Quaternion& v) {
c[0] -= v[0];
c[1] -= v[1];
c[2] -= v[2];
c[3] -= v[3];
return *this;
}
Quaternion& Quaternion::operator *=(const Quaternion& v) {
float t0 = (c[3]-c[2])*(v[2]-v[3]);
float t1 = (c[0]+c[1])*(v[0]+v[1]);
float t2 = (c[0]-c[1])*(v[2]+v[3]);
float t3 = (c[3]+c[2])*(v[0]-v[1]);
float t4 = (c[3]-c[1])*(v[1]-v[2]);
float t5 = (c[3]+c[1])*(v[1]+v[2]);
float t6 = (c[0]+c[2])*(v[0]-v[3]);
float t7 = (c[0]-c[2])*(v[0]+v[3]);
float t8 = t5+t6+t7;
float t9 = (t4+t8)/2;
c[0] = t0+t9-t5;
c[1] = t1+t9-t8;
c[2] = t2+t9-t7;
c[3] = t3+t9-t6;
return *this;
}
Quaternion& Quaternion::operator *=(const float& v) {
c[0] *= v;
c[1] *= v;
c[2] *= v;
c[3] *= v;
return *this;
}
Quaternion& Quaternion::operator /=(const float& v) {
float inv_v = 1.0f / v;
c[0] *= inv_v;
c[1] *= inv_v;
c[2] *= inv_v;
c[3] *= inv_v;
return *this;
}
Quaternion Quaternion::operator +() const {
return *this;
}
Quaternion Quaternion::operator -() const {
return Quaternion::Create(-c[0], -c[1], -c[2], -c[3]);
}
Quaternion Quaternion::Normalize(const Quaternion &v1) {
float inv_magnitude = 1.0f / sqrtf(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] + v1[3] * v1[3]);
return Quaternion::Create(
v1[0] * inv_magnitude,
v1[1] * inv_magnitude,
v1[2] * inv_magnitude,
v1[3] * inv_magnitude
); );
} else {
return Vector3::Create(
atan2f(2 * (c[0] * c[1] + c[2] * c[3]), (1 - 2 * (c[1] * c[1] + c[2] * c[2]))),
asinf(a2),
atan2f(2 * (c[0] * c[3] + c[1] * c[2]), (1 - 2 * (c[2] * c[2] + c[3] * c[3])))
);
}
} }
void Quaternion::normalize() { bool operator ==(Quaternion& v1, Quaternion& v2)
float inv_magnitude = 1.0f / sqrtf(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]); {
c[0] *= inv_magnitude; return
c[1] *= inv_magnitude; v1[0] == v2[0]
c[2] *= inv_magnitude; && v1[1] == v2[1]
c[3] *= inv_magnitude; && v1[2] == v2[2]
&& v1[3] == v2[3];
} }
Quaternion Quaternion::Conjugate(const Quaternion &v1) { bool operator !=(Quaternion& v1, Quaternion& v2)
return Quaternion::Create(v1[0], -v1[1], -v1[2], -v1[3]); {
return
v1[0] != v2[0]
|| v1[1] != v2[1]
|| v1[2] != v2[2]
|| v1[3] != v2[3];
} }
void Quaternion::conjugate() { Quaternion Quaternion::operator *(const Quaternion& v)
c[1] = -c[1]; {
c[2] = -c[2]; float t0 = (c[3] - c[2]) * (v[2] - v[3]);
c[3] = -c[3]; float t1 = (c[0] + c[1]) * (v[0] + v[1]);
float t2 = (c[0] - c[1]) * (v[2] + v[3]);
float t3 = (c[3] + c[2]) * (v[0] - v[1]);
float t4 = (c[3] - c[1]) * (v[1] - v[2]);
float t5 = (c[3] + c[1]) * (v[1] + v[2]);
float t6 = (c[0] + c[2]) * (v[0] - v[3]);
float t7 = (c[0] - c[2]) * (v[0] + v[3]);
float t8 = t5 + t6 + t7;
float t9 = (t4 + t8) / 2;
return Quaternion::Create(
t0 + t9 - t5,
t1 + t9 - t8,
t2 + t9 - t7,
t3 + t9 - t6
);
} }
void Quaternion::invert() { Quaternion Quaternion::operator *(float v) const
{
return Quaternion::Create(c[0] * v, c[1] * v, c[2] * v, c[3] * v);
}
Quaternion Quaternion::operator /(float num) const
{
float inv_num = 1.0f / num;
return Quaternion::Create(c[0] * inv_num, c[1] * inv_num, c[2] * inv_num, c[3] * inv_num);
}
Quaternion Quaternion::operator +(const Quaternion& v) const
{
return Quaternion::Create(c[0] + v[0], c[1] + v[1], c[2] + v[2], c[3] + v[3]);
}
Quaternion Quaternion::operator -(const Quaternion& v) const
{
return Quaternion::Create(c[0] - v[0], c[1] - v[1], c[2] - v[2], c[3] - v[3]);
}
Quaternion& Quaternion::operator +=(const Quaternion& v)
{
c[0] += v[0];
c[1] += v[1];
c[2] += v[2];
c[3] += v[3];
return *this;
}
Quaternion& Quaternion::operator -=(const Quaternion& v)
{
c[0] -= v[0];
c[1] -= v[1];
c[2] -= v[2];
c[3] -= v[3];
return *this;
}
Quaternion& Quaternion::operator *=(const Quaternion& v)
{
float t0 = (c[3] - c[2]) * (v[2] - v[3]);
float t1 = (c[0] + c[1]) * (v[0] + v[1]);
float t2 = (c[0] - c[1]) * (v[2] + v[3]);
float t3 = (c[3] + c[2]) * (v[0] - v[1]);
float t4 = (c[3] - c[1]) * (v[1] - v[2]);
float t5 = (c[3] + c[1]) * (v[1] + v[2]);
float t6 = (c[0] + c[2]) * (v[0] - v[3]);
float t7 = (c[0] - c[2]) * (v[0] + v[3]);
float t8 = t5 + t6 + t7;
float t9 = (t4 + t8) / 2;
c[0] = t0 + t9 - t5;
c[1] = t1 + t9 - t8;
c[2] = t2 + t9 - t7;
c[3] = t3 + t9 - t6;
return *this;
}
Quaternion& Quaternion::operator *=(const float& v)
{
c[0] *= v;
c[1] *= v;
c[2] *= v;
c[3] *= v;
return *this;
}
Quaternion& Quaternion::operator /=(const float& v)
{
float inv_v = 1.0f / v;
c[0] *= inv_v;
c[1] *= inv_v;
c[2] *= inv_v;
c[3] *= inv_v;
return *this;
}
Quaternion Quaternion::operator +() const
{
return *this;
}
Quaternion Quaternion::operator -() const
{
return Quaternion::Create(-c[0], -c[1], -c[2], -c[3]);
}
Quaternion Quaternion::Normalize(const Quaternion& v1)
{
float inv_magnitude = 1.0f / sqrtf(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] + v1[3] * v1[3]);
return Quaternion::Create(
v1[0] * inv_magnitude,
v1[1] * inv_magnitude,
v1[2] * inv_magnitude,
v1[3] * inv_magnitude
);
}
void Quaternion::normalize()
{
float inv_magnitude = 1.0f / sqrtf(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
c[0] *= inv_magnitude;
c[1] *= inv_magnitude;
c[2] *= inv_magnitude;
c[3] *= inv_magnitude;
}
Quaternion Quaternion::Conjugate(const Quaternion& v1)
{
return Quaternion::Create(v1[0], -v1[1], -v1[2], -v1[3]);
}
void Quaternion::conjugate()
{
c[1] = -c[1];
c[2] = -c[2];
c[3] = -c[3];
}
void Quaternion::invert()
{
conjugate(); conjugate();
normalize(); normalize();
} }
Quaternion Quaternion::Invert(const Quaternion &v1) { Quaternion Quaternion::Invert(const Quaternion& v1)
{
return Normalize(Conjugate(v1)); return Normalize(Conjugate(v1));
} }
Matrix4 Quaternion::rotationMatrix() const { Matrix4 Quaternion::rotationMatrix() const
Matrix4 matRotate; {
matRotate.init(); Matrix4 matRotate;
matRotate.init();
/*
Vector3 euler = eulerXYZ(); /*
Vector3 euler = eulerXYZ();
matRotate.rotate(euler.x, X_AXIS);
matRotate.rotate(euler.y, Y_AXIS); matRotate.rotate(euler.x, X_AXIS);
matRotate.rotate(euler.z, Z_AXIS); matRotate.rotate(euler.y, Y_AXIS);
*/ matRotate.rotate(euler.z, Z_AXIS);
*/
// FINDME - Determine why the more optimal routine commented below wasn't working
// FINDME - Determine why the more optimal routine commented below wasn't working
matRotate.c[0] = 1.0f - 2.0f * (c[2] * c[2] + c[3] * c[3]);
matRotate.c[1] = 2.0f * (c[1] * c[2] - c[0] * c[3]); matRotate.c[0] = 1.0f - 2.0f * (c[2] * c[2] + c[3] * c[3]);
matRotate.c[2] = 2.0f * (c[0] * c[2] + c[1] * c[3]); matRotate.c[1] = 2.0f * (c[1] * c[2] - c[0] * c[3]);
matRotate.c[2] = 2.0f * (c[0] * c[2] + c[1] * c[3]);
matRotate.c[4] = 2.0f * (c[1] * c[2] + c[0] * c[3]);
matRotate.c[5] = 1.0f - 2.0f * (c[1] * c[1] + c[3] * c[3]); matRotate.c[4] = 2.0f * (c[1] * c[2] + c[0] * c[3]);
matRotate.c[6] = 2.0f * (c[2] * c[3] - c[0] * c[1]); matRotate.c[5] = 1.0f - 2.0f * (c[1] * c[1] + c[3] * c[3]);
matRotate.c[6] = 2.0f * (c[2] * c[3] - c[0] * c[1]);
matRotate.c[8] = 2.0f * (c[1] * c[3] - c[0] * c[2]);
matRotate.c[9] = 2.0f * (c[0] * c[1] + c[2] * c[3]); matRotate.c[8] = 2.0f * (c[1] * c[3] - c[0] * c[2]);
matRotate.c[10] = 1.0f - 2.0f * (c[1] * c[1] + c[2] * c[2]); matRotate.c[9] = 2.0f * (c[0] * c[1] + c[2] * c[3]);
matRotate.c[10] = 1.0f - 2.0f * (c[1] * c[1] + c[2] * c[2]);
return matRotate;
return matRotate;
} }
Quaternion Quaternion::FromAngleAxis(const Vector3 &axis, float angle) Quaternion Quaternion::FromAngleAxis(const Vector3& axis, float angle)
{ {
float ha = angle * 0.5f; float ha = angle * 0.5f;
float sha = sinf(ha); float sha = sinf(ha);
return Quaternion::Create(cosf(ha), axis.x * sha, axis.y * sha, axis.z * sha); return Quaternion::Create(cosf(ha), axis.x * sha, axis.y * sha, axis.z * sha);
} }
Quaternion Quaternion::FromRotationMatrix(const Matrix4 &m) Quaternion Quaternion::FromRotationMatrix(const Matrix4& m)
{ {
// see http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm // see http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
const float trace = m[0] + m[5] + m[10]; const float trace = m[0] + m[5] + m[10];
float w, x, y, z; float w, x, y, z;
if (trace > 0.0) { if (trace > 0.0) {
@@ -379,53 +409,53 @@ Quaternion Quaternion::FromRotationMatrix(const Matrix4 &m)
y = (m[6] + m[9]) / s; y = (m[6] + m[9]) / s;
z = 0.25f * s; z = 0.25f * s;
} }
return Quaternion::Create(w, x, y, z); return Quaternion::Create(w, x, y, z);
} }
float Quaternion::Dot(const Quaternion &v1, const Quaternion &v2) float Quaternion::Dot(const Quaternion& v1, const Quaternion& v2)
{ {
return v1.c[0] * v2.c[0] + v1.c[1] * v2.c[1] + v1.c[2] * v2.c[2] + v1.c[3] * v2.c[3]; return v1.c[0] * v2.c[0] + v1.c[1] * v2.c[1] + v1.c[2] * v2.c[2] + v1.c[3] * v2.c[3];
} }
Quaternion Quaternion::Lerp(const Quaternion &a, const Quaternion &b, float t) Quaternion Quaternion::Lerp(const Quaternion& a, const Quaternion& b, float t)
{ {
if (t <= 0.0f) { if (t <= 0.0f) {
return a; return a;
} else if (t >= 1.0f) { } else if (t >= 1.0f) {
return b; return b;
} }
return a * (1.0f - t) + b * t; return a * (1.0f - t) + b * t;
} }
Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, float t) Quaternion Quaternion::Slerp(const Quaternion& a, const Quaternion& b, float t)
{ {
if (t <= 0.0f) { if (t <= 0.0f) {
return a; return a;
} }
if (t >= 1.0f) { if (t >= 1.0f) {
return b; return b;
} }
float coshalftheta = Dot(a, b); float coshalftheta = Dot(a, b);
Quaternion c = a; Quaternion c = a;
// Angle is greater than 180. We can negate the angle/quat to get the // Angle is greater than 180. We can negate the angle/quat to get the
// shorter rotation to reach the same destination. // shorter rotation to reach the same destination.
if ( coshalftheta < 0.0f ) { if (coshalftheta < 0.0f) {
coshalftheta = -coshalftheta; coshalftheta = -coshalftheta;
c = -c; c = -c;
} }
if ( coshalftheta > (1.0f - std::numeric_limits<float>::epsilon())) { if (coshalftheta > (1.0f - std::numeric_limits<float>::epsilon())) {
// Angle is tiny - save some computation by lerping instead. // Angle is tiny - save some computation by lerping instead.
return Lerp(c, b, t); return Lerp(c, b, t);
} }
float halftheta = acosf(coshalftheta); float halftheta = acosf(coshalftheta);
return (c * sinf((1.0f - t) * halftheta) + b * sinf(t * halftheta)) / sinf(halftheta); return (c * sinf((1.0f - t) * halftheta) + b * sinf(t * halftheta)) / sinf(halftheta);
} }
} // namespace kraken } // namespace kraken

View File

@@ -35,8 +35,8 @@ namespace kraken {
float SmoothStep(float a, float b, float t) float SmoothStep(float a, float b, float t)
{ {
float d = (3.0f * t * t - 2.0f * t * t * t); float d = (3.0f * t * t - 2.0f * t * t * t);
return a * (1.0f - d) + b * d; return a * (1.0f - d) + b * d;
} }
float Lerp(float a, float b, float t) float Lerp(float a, float b, float t)

View File

@@ -34,92 +34,92 @@
using namespace kraken; using namespace kraken;
namespace { namespace {
bool _intersectSphere(const Vector3 &start, const Vector3 &dir, const Vector3 &sphere_center, float sphere_radius, float &distance) bool _intersectSphere(const Vector3& start, const Vector3& dir, const Vector3& sphere_center, float sphere_radius, float& distance)
{ {
// dir must be normalized // dir must be normalized
// From: http://archive.gamedev.net/archive/reference/articles/article1026.html // From: http://archive.gamedev.net/archive/reference/articles/article1026.html
// TODO - Move to another class? // TODO - Move to another class?
Vector3 Q = sphere_center - start; Vector3 Q = sphere_center - start;
float c = Q.magnitude(); float c = Q.magnitude();
float v = Vector3::Dot(Q, dir); float v = Vector3::Dot(Q, dir);
float d = sphere_radius * sphere_radius - (c * c - v * v); float d = sphere_radius * sphere_radius - (c * c - v * v);
if (d < 0.0) { if (d < 0.0) {
// No intersection // No intersection
return false;
}
// Return the distance to the [first] intersecting point
distance = v - sqrtf(d);
if (distance < 0.0f) {
return false;
}
return true;
}
bool _sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b)
{
// TODO - Move to Vector3 class?
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
Vector3 cp1 = Vector3::Cross(b - a, p1 - a);
Vector3 cp2 = Vector3::Cross(b - a, p2 - a);
if (Vector3::Dot(cp1, cp2) >= 0) return true;
return false; return false;
} }
Vector3 _closestPointOnLine(const Vector3 &a, const Vector3 &b, const Vector3 &p) // Return the distance to the [first] intersecting point
{
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
// Determine t (the length of the vector from a to p) distance = v - sqrtf(d);
if (distance < 0.0f) {
Vector3 c = p - a; return false;
Vector3 V = Vector3::Normalize(b - a);
float d = (a - b).magnitude();
float t = Vector3::Dot(V, c);
// Check to see if t is beyond the extents of the line segment
if (t < 0) return a;
if (t > d) return b;
// Return the point between a and b
return a + V * t;
} }
return true;
}
bool _sameSide(const Vector3& p1, const Vector3& p2, const Vector3& a, const Vector3& b)
{
// TODO - Move to Vector3 class?
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
Vector3 cp1 = Vector3::Cross(b - a, p1 - a);
Vector3 cp2 = Vector3::Cross(b - a, p2 - a);
if (Vector3::Dot(cp1, cp2) >= 0) return true;
return false;
}
Vector3 _closestPointOnLine(const Vector3& a, const Vector3& b, const Vector3& p)
{
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
// Determine t (the length of the vector from a to p)
Vector3 c = p - a;
Vector3 V = Vector3::Normalize(b - a);
float d = (a - b).magnitude();
float t = Vector3::Dot(V, c);
// Check to see if t is beyond the extents of the line segment
if (t < 0) return a;
if (t > d) return b;
// Return the point between a and b
return a + V * t;
}
} // anonymous namespace } // anonymous namespace
namespace kraken { namespace kraken {
void Triangle3::init(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) void Triangle3::init(const Vector3& v1, const Vector3& v2, const Vector3& v3)
{ {
vert[0] = v1; vert[0] = v1;
vert[1] = v2; vert[1] = v2;
vert[2] = v3; vert[2] = v3;
} }
void Triangle3::init(const Triangle3 &tri) void Triangle3::init(const Triangle3& tri)
{ {
vert[0] = tri[0]; vert[0] = tri[0];
vert[1] = tri[1]; vert[1] = tri[1];
vert[2] = tri[2]; vert[2] = tri[2];
} }
Triangle3 Triangle3::Create(const Triangle3 &tri) Triangle3 Triangle3::Create(const Triangle3& tri)
{ {
Triangle3 r; Triangle3 r;
r.init(tri); r.init(tri);
return r; return r;
} }
Triangle3 Triangle3::Create(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) Triangle3 Triangle3::Create(const Vector3& v1, const Vector3& v2, const Vector3& v3)
{ {
Triangle3 r; Triangle3 r;
r.init(v1, v2, v3); r.init(v1, v2, v3);
@@ -128,226 +128,226 @@ Triangle3 Triangle3::Create(const Vector3 &v1, const Vector3 &v2, const Vector3
bool Triangle3::operator ==(const Triangle3& b) const bool Triangle3::operator ==(const Triangle3& b) const
{ {
return vert[0] == b[0] && vert[1] == b[1] && vert[2] == b[2]; return vert[0] == b[0] && vert[1] == b[1] && vert[2] == b[2];
} }
bool Triangle3::operator !=(const Triangle3& b) const bool Triangle3::operator !=(const Triangle3& b) const
{ {
return vert[0] != b[0] || vert[1] != b[1] || vert[2] != b[2]; return vert[0] != b[0] || vert[1] != b[1] || vert[2] != b[2];
} }
Vector3& Triangle3::operator[](unsigned int i) Vector3& Triangle3::operator[](unsigned int i)
{ {
return vert[i]; return vert[i];
} }
Vector3 Triangle3::operator[](unsigned int i) const Vector3 Triangle3::operator[](unsigned int i) const
{ {
return vert[i]; return vert[i];
} }
bool Triangle3::rayCast(const Vector3 &start, const Vector3 &dir, Vector3 &hit_point) const bool Triangle3::rayCast(const Vector3& start, const Vector3& dir, Vector3& hit_point) const
{ {
// algorithm based on Dan Sunday's implementation at http://geomalgorithms.com/a06-_intersect-2.html // algorithm based on Dan Sunday's implementation at http://geomalgorithms.com/a06-_intersect-2.html
const float SMALL_NUM = 0.00000001f; // anything that avoids division overflow const float SMALL_NUM = 0.00000001f; // anything that avoids division overflow
Vector3 u, v, n; // triangle vectors Vector3 u, v, n; // triangle vectors
Vector3 w0, w; // ray vectors Vector3 w0, w; // ray vectors
float r, a, b; // params to calc ray-plane intersect float r, a, b; // params to calc ray-plane intersect
// get triangle edge vectors and plane normal
u = vert[1] - vert[0];
v = vert[2] - vert[0];
n = Vector3::Cross(u, v); // cross product
if (n == Vector3::Zero()) // triangle is degenerate
return false; // do not deal with this case
w0 = start - vert[0];
a = -Vector3::Dot(n, w0);
b = Vector3::Dot(n,dir);
if (fabs(b) < SMALL_NUM) { // ray is parallel to triangle plane
if (a == 0)
return false; // ray lies in triangle plane
else {
return false; // ray disjoint from plane
}
}
// get intersect point of ray with triangle plane
r = a / b;
if (r < 0.0f) // ray goes away from triangle
return false; // => no intersect
// for a segment, also test if (r > 1.0) => no intersect
Vector3 plane_hit_point = start + dir * r; // intersect point of ray and plane
// is plane_hit_point inside triangle?
float uu, uv, vv, wu, wv, D;
uu = Vector3::Dot(u,u);
uv = Vector3::Dot(u,v);
vv = Vector3::Dot(v,v);
w = plane_hit_point - vert[0];
wu = Vector3::Dot(w,u);
wv = Vector3::Dot(w,v);
D = uv * uv - uu * vv;
// get and test parametric coords
float s, t;
s = (uv * wv - vv * wu) / D;
if (s < 0.0f || s > 1.0f) // plane_hit_point is outside triangle
return false;
t = (uv * wu - uu * wv) / D;
if (t < 0.0f || (s + t) > 1.0f) // plane_hit_point is outside triangle
return false;
// plane_hit_point is inside the triangle // get triangle edge vectors and plane normal
hit_point = plane_hit_point; u = vert[1] - vert[0];
return true; v = vert[2] - vert[0];
n = Vector3::Cross(u, v); // cross product
if (n == Vector3::Zero()) // triangle is degenerate
return false; // do not deal with this case
w0 = start - vert[0];
a = -Vector3::Dot(n, w0);
b = Vector3::Dot(n, dir);
if (fabs(b) < SMALL_NUM) { // ray is parallel to triangle plane
if (a == 0)
return false; // ray lies in triangle plane
else {
return false; // ray disjoint from plane
}
}
// get intersect point of ray with triangle plane
r = a / b;
if (r < 0.0f) // ray goes away from triangle
return false; // => no intersect
// for a segment, also test if (r > 1.0) => no intersect
Vector3 plane_hit_point = start + dir * r; // intersect point of ray and plane
// is plane_hit_point inside triangle?
float uu, uv, vv, wu, wv, D;
uu = Vector3::Dot(u, u);
uv = Vector3::Dot(u, v);
vv = Vector3::Dot(v, v);
w = plane_hit_point - vert[0];
wu = Vector3::Dot(w, u);
wv = Vector3::Dot(w, v);
D = uv * uv - uu * vv;
// get and test parametric coords
float s, t;
s = (uv * wv - vv * wu) / D;
if (s < 0.0f || s > 1.0f) // plane_hit_point is outside triangle
return false;
t = (uv * wu - uu * wv) / D;
if (t < 0.0f || (s + t) > 1.0f) // plane_hit_point is outside triangle
return false;
// plane_hit_point is inside the triangle
hit_point = plane_hit_point;
return true;
} }
Vector3 Triangle3::calculateNormal() const Vector3 Triangle3::calculateNormal() const
{ {
Vector3 v1 = vert[1] - vert[0]; Vector3 v1 = vert[1] - vert[0];
Vector3 v2 = vert[2] - vert[0]; Vector3 v2 = vert[2] - vert[0];
return Vector3::Normalize(Vector3::Cross(v1, v2)); return Vector3::Normalize(Vector3::Cross(v1, v2));
} }
Vector3 Triangle3::closestPointOnTriangle(const Vector3 &p) const Vector3 Triangle3::closestPointOnTriangle(const Vector3& p) const
{ {
Vector3 a = vert[0]; Vector3 a = vert[0];
Vector3 b = vert[1]; Vector3 b = vert[1];
Vector3 c = vert[2]; Vector3 c = vert[2];
Vector3 Rab = _closestPointOnLine(a, b, p); Vector3 Rab = _closestPointOnLine(a, b, p);
Vector3 Rbc = _closestPointOnLine(b, c, p); Vector3 Rbc = _closestPointOnLine(b, c, p);
Vector3 Rca = _closestPointOnLine(c, a, p); Vector3 Rca = _closestPointOnLine(c, a, p);
// return closest [Rab, Rbc, Rca] to p; // return closest [Rab, Rbc, Rca] to p;
float sd_Rab = (p - Rab).sqrMagnitude(); float sd_Rab = (p - Rab).sqrMagnitude();
float sd_Rbc = (p - Rbc).sqrMagnitude(); float sd_Rbc = (p - Rbc).sqrMagnitude();
float sd_Rca = (p - Rca).sqrMagnitude(); float sd_Rca = (p - Rca).sqrMagnitude();
if(sd_Rab < sd_Rbc && sd_Rab < sd_Rca) { if (sd_Rab < sd_Rbc && sd_Rab < sd_Rca) {
return Rab; return Rab;
} else if(sd_Rbc < sd_Rab && sd_Rbc < sd_Rca) { } else if (sd_Rbc < sd_Rab && sd_Rbc < sd_Rca) {
return Rbc; return Rbc;
} else { } else {
return Rca; return Rca;
} }
} }
bool Triangle3::sphereCast(const Vector3 &start, const Vector3 &dir, float radius, Vector3 &hit_point, float &hit_distance) const bool Triangle3::sphereCast(const Vector3& start, const Vector3& dir, float radius, Vector3& hit_point, float& hit_distance) const
{ {
// Dir must be normalized // Dir must be normalized
const float SMALL_NUM = 0.001f; // anything that avoids division overflow const float SMALL_NUM = 0.001f; // anything that avoids division overflow
Vector3 tri_normal = calculateNormal();
float d = Vector3::Dot(tri_normal, vert[0]);
float e = Vector3::Dot(tri_normal, start) - radius;
float cotangent_distance = e - d;
Vector3 plane_intersect;
float plane_intersect_distance;
float denom = Vector3::Dot(tri_normal, dir);
if(denom > -SMALL_NUM) {
return false; // dir is co-planar with the triangle or going in the direction of the normal; no intersection
}
// Detect an embedded plane, caused by a sphere that is already intersecting the plane. Vector3 tri_normal = calculateNormal();
if(cotangent_distance <= 0 && cotangent_distance >= -radius * 2.0f) {
// Embedded plane - Sphere is already intersecting the plane.
// Use the point closest to the origin of the sphere as the intersection
plane_intersect = start - tri_normal * (cotangent_distance + radius);
plane_intersect_distance = 0.0f;
} else {
// Sphere is not intersecting the plane
// Determine the first point hit by the swept sphere on the triangle's plane
plane_intersect_distance = -(cotangent_distance / denom);
plane_intersect = start + dir * plane_intersect_distance - tri_normal * radius;
}
if(plane_intersect_distance < 0.0f) {
return false;
}
if(containsPoint(plane_intersect)) {
// Triangle contains point
hit_point = plane_intersect;
hit_distance = plane_intersect_distance;
return true;
} else {
// Triangle does not contain point, cast ray back to sphere from closest point on triangle edge or vertice
Vector3 closest_point = closestPointOnTriangle(plane_intersect);
float reverse_hit_distance;
if(_intersectSphere(closest_point, -dir, start, radius, reverse_hit_distance)) {
// Reverse cast hit sphere
hit_distance = reverse_hit_distance;
hit_point = closest_point;
return true;
} else {
// Reverse cast did not hit sphere
return false;
}
}
}
float d = Vector3::Dot(tri_normal, vert[0]);
float e = Vector3::Dot(tri_normal, start) - radius;
float cotangent_distance = e - d;
bool Triangle3::containsPoint(const Vector3 &p) const Vector3 plane_intersect;
{ float plane_intersect_distance;
/*
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle float denom = Vector3::Dot(tri_normal, dir);
const float SMALL_NUM = 0.00000001f; // anything that avoids division overflow if (denom > -SMALL_NUM) {
// Vector3 A = vert[0], B = vert[1], C = vert[2]; return false; // dir is co-planar with the triangle or going in the direction of the normal; no intersection
if (_sameSide(p, vert[0], vert[1], vert[2]) && _sameSide(p, vert[1], vert[0], vert[2]) && _sameSide(p, vert[2], vert[0], vert[1])) { }
Vector3 vc1 = Vector3::Cross(vert[0] - vert[1], vert[0] - vert[2]);
if(fabs(Vector3::Dot(vert[0] - p, vc1)) <= SMALL_NUM) { // Detect an embedded plane, caused by a sphere that is already intersecting the plane.
return true; if (cotangent_distance <= 0 && cotangent_distance >= -radius * 2.0f) {
} // Embedded plane - Sphere is already intersecting the plane.
} // Use the point closest to the origin of the sphere as the intersection
plane_intersect = start - tri_normal * (cotangent_distance + radius);
plane_intersect_distance = 0.0f;
} else {
// Sphere is not intersecting the plane
// Determine the first point hit by the swept sphere on the triangle's plane
plane_intersect_distance = -(cotangent_distance / denom);
plane_intersect = start + dir * plane_intersect_distance - tri_normal * radius;
}
if (plane_intersect_distance < 0.0f) {
return false; return false;
*/ }
// From: http://blogs.msdn.com/b/rezanour/archive/2011/08/07/barycentric-coordinates-and-point-in-triangle-tests.aspx if (containsPoint(plane_intersect)) {
// Triangle contains point
Vector3 A = vert[0]; hit_point = plane_intersect;
Vector3 B = vert[1]; hit_distance = plane_intersect_distance;
Vector3 C = vert[2]; return true;
Vector3 P = p; } else {
// Triangle does not contain point, cast ray back to sphere from closest point on triangle edge or vertice
// Prepare our barycentric variables Vector3 closest_point = closestPointOnTriangle(plane_intersect);
Vector3 u = B - A; float reverse_hit_distance;
Vector3 v = C - A; if (_intersectSphere(closest_point, -dir, start, radius, reverse_hit_distance)) {
Vector3 w = P - A; // Reverse cast hit sphere
hit_distance = reverse_hit_distance;
Vector3 vCrossW = Vector3::Cross(v, w); hit_point = closest_point;
Vector3 vCrossU = Vector3::Cross(v, u); return true;
} else {
// Test sign of r // Reverse cast did not hit sphere
if (Vector3::Dot(vCrossW, vCrossU) < 0) return false;
return false; }
}
Vector3 uCrossW = Vector3::Cross(u, w); }
Vector3 uCrossV = Vector3::Cross(u, v);
// Test sign of t bool Triangle3::containsPoint(const Vector3& p) const
if (Vector3::Dot(uCrossW, uCrossV) < 0) {
return false; /*
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
// At this point, we know that r and t and both > 0.
// Therefore, as long as their sum is <= 1, each must be less <= 1 const float SMALL_NUM = 0.00000001f; // anything that avoids division overflow
float denom = uCrossV.magnitude(); // Vector3 A = vert[0], B = vert[1], C = vert[2];
float r = vCrossW.magnitude() / denom; if (_sameSide(p, vert[0], vert[1], vert[2]) && _sameSide(p, vert[1], vert[0], vert[2]) && _sameSide(p, vert[2], vert[0], vert[1])) {
float t = uCrossW.magnitude() / denom; Vector3 vc1 = Vector3::Cross(vert[0] - vert[1], vert[0] - vert[2]);
if(fabs(Vector3::Dot(vert[0] - p, vc1)) <= SMALL_NUM) {
return (r + t <= 1); return true;
}
}
return false;
*/
// From: http://blogs.msdn.com/b/rezanour/archive/2011/08/07/barycentric-coordinates-and-point-in-triangle-tests.aspx
Vector3 A = vert[0];
Vector3 B = vert[1];
Vector3 C = vert[2];
Vector3 P = p;
// Prepare our barycentric variables
Vector3 u = B - A;
Vector3 v = C - A;
Vector3 w = P - A;
Vector3 vCrossW = Vector3::Cross(v, w);
Vector3 vCrossU = Vector3::Cross(v, u);
// Test sign of r
if (Vector3::Dot(vCrossW, vCrossU) < 0)
return false;
Vector3 uCrossW = Vector3::Cross(u, w);
Vector3 uCrossV = Vector3::Cross(u, v);
// Test sign of t
if (Vector3::Dot(uCrossW, uCrossV) < 0)
return false;
// At this point, we know that r and t and both > 0.
// Therefore, as long as their sum is <= 1, each must be less <= 1
float denom = uCrossV.magnitude();
float r = vCrossW.magnitude() / denom;
float t = uCrossW.magnitude() / denom;
return (r + t <= 1);
} }
} // namespace kraken } // namespace kraken

View File

@@ -34,237 +34,268 @@
namespace kraken { namespace kraken {
void Vector2::init() { void Vector2::init()
x = 0.0; {
y = 0.0; x = 0.0;
y = 0.0;
} }
Vector2 Vector2::Create() Vector2 Vector2::Create()
{ {
Vector2 r; Vector2 r;
r.init(); r.init();
return r; return r;
} }
void Vector2::init(float X, float Y) { void Vector2::init(float X, float Y)
x = X; {
y = Y; x = X;
y = Y;
} }
Vector2 Vector2::Create(float X, float Y) Vector2 Vector2::Create(float X, float Y)
{ {
Vector2 r; Vector2 r;
r.init(X,Y); r.init(X, Y);
return r; return r;
} }
void Vector2::init(float v) { void Vector2::init(float v)
x = v; {
y = v; x = v;
y = v;
} }
Vector2 Vector2::Create(float v) Vector2 Vector2::Create(float v)
{ {
Vector2 r; Vector2 r;
r.init(v); r.init(v);
return r; return r;
} }
void Vector2::init(float *v) { void Vector2::init(float* v)
x = v[0];
y = v[1];
}
Vector2 Vector2::Create(float *v)
{ {
Vector2 r; x = v[0];
r.init(v); y = v[1];
return r;
} }
void Vector2::init(const Vector2 &v) { Vector2 Vector2::Create(float* v)
x = v.x;
y = v.y;
}
Vector2 Vector2::Create(const Vector2 &v)
{ {
Vector2 r; Vector2 r;
r.init(v); r.init(v);
return r; return r;
}
void Vector2::init(const Vector2& v)
{
x = v.x;
y = v.y;
}
Vector2 Vector2::Create(const Vector2& v)
{
Vector2 r;
r.init(v);
return r;
} }
// Vector2 swizzle getters // Vector2 swizzle getters
Vector2 Vector2::yx() const Vector2 Vector2::yx() const
{ {
return Vector2::Create(y,x); return Vector2::Create(y, x);
} }
// Vector2 swizzle setters // Vector2 swizzle setters
void Vector2::yx(const Vector2 &v) void Vector2::yx(const Vector2& v)
{ {
y = v.x; y = v.x;
x = v.y; x = v.y;
} }
Vector2 Vector2::Min() { Vector2 Vector2::Min()
return Vector2::Create(-std::numeric_limits<float>::max()); {
return Vector2::Create(-std::numeric_limits<float>::max());
} }
Vector2 Vector2::Max() { Vector2 Vector2::Max()
return Vector2::Create(std::numeric_limits<float>::max()); {
return Vector2::Create(std::numeric_limits<float>::max());
} }
Vector2 Vector2::Zero() { Vector2 Vector2::Zero()
return Vector2::Create(0.0f); {
return Vector2::Create(0.0f);
} }
Vector2 Vector2::One() { Vector2 Vector2::One()
return Vector2::Create(1.0f); {
return Vector2::Create(1.0f);
} }
Vector2 Vector2::operator +(const Vector2& b) const { Vector2 Vector2::operator +(const Vector2& b) const
return Vector2::Create(x + b.x, y + b.y); {
return Vector2::Create(x + b.x, y + b.y);
} }
Vector2 Vector2::operator -(const Vector2& b) const { Vector2 Vector2::operator -(const Vector2& b) const
return Vector2::Create(x - b.x, y - b.y); {
return Vector2::Create(x - b.x, y - b.y);
} }
Vector2 Vector2::operator +() const { Vector2 Vector2::operator +() const
return *this; {
return *this;
} }
Vector2 Vector2::operator -() const { Vector2 Vector2::operator -() const
return Vector2::Create(-x, -y); {
return Vector2::Create(-x, -y);
} }
Vector2 Vector2::operator *(const float v) const { Vector2 Vector2::operator *(const float v) const
return Vector2::Create(x * v, y * v); {
return Vector2::Create(x * v, y * v);
} }
Vector2 Vector2::operator /(const float v) const { Vector2 Vector2::operator /(const float v) const
float inv_v = 1.0f / v; {
return Vector2::Create(x * inv_v, y * inv_v); float inv_v = 1.0f / v;
return Vector2::Create(x * inv_v, y * inv_v);
} }
Vector2& Vector2::operator +=(const Vector2& b) { Vector2& Vector2::operator +=(const Vector2& b)
x += b.x; {
y += b.y; x += b.x;
return *this; y += b.y;
return *this;
} }
Vector2& Vector2::operator -=(const Vector2& b) { Vector2& Vector2::operator -=(const Vector2& b)
x -= b.x; {
y -= b.y; x -= b.x;
return *this; y -= b.y;
return *this;
} }
Vector2& Vector2::operator *=(const float v) { Vector2& Vector2::operator *=(const float v)
x *= v; {
y *= v; x *= v;
return *this; y *= v;
return *this;
} }
Vector2& Vector2::operator /=(const float v) { Vector2& Vector2::operator /=(const float v)
float inv_v = 1.0f / v; {
x *= inv_v; float inv_v = 1.0f / v;
y *= inv_v; x *= inv_v;
return *this; y *= inv_v;
return *this;
} }
bool Vector2::operator ==(const Vector2& b) const { bool Vector2::operator ==(const Vector2& b) const
return x == b.x && y == b.y; {
return x == b.x && y == b.y;
} }
bool Vector2::operator !=(const Vector2& b) const { bool Vector2::operator !=(const Vector2& b) const
return x != b.x || y != b.y; {
return x != b.x || y != b.y;
} }
bool Vector2::operator >(const Vector2& b) const bool Vector2::operator >(const Vector2& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x > b.x) { if (x > b.x) {
return true; return true;
} else if(x < b.x) { } else if (x < b.x) {
return false; return false;
} else if(y > b.y) { } else if (y > b.y) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool Vector2::operator <(const Vector2& b) const bool Vector2::operator <(const Vector2& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x < b.x) { if (x < b.x) {
return true; return true;
} else if(x > b.x) { } else if (x > b.x) {
return false; return false;
} else if(y < b.y) { } else if (y < b.y) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
float& Vector2::operator[] (unsigned i) { float& Vector2::operator[] (unsigned i)
switch(i) { {
case 0: switch (i) {
return x; case 0:
case 1: return x;
default: case 1:
return y; default:
} return y;
}
} }
float Vector2::operator[](unsigned i) const { float Vector2::operator[](unsigned i) const
switch(i) { {
case 0: switch (i) {
return x; case 0:
case 1: return x;
default: case 1:
return y; default:
} return y;
}
} }
void Vector2::normalize() { void Vector2::normalize()
float inv_magnitude = 1.0f / sqrtf(x * x + y * y); {
x *= inv_magnitude; float inv_magnitude = 1.0f / sqrtf(x * x + y * y);
y *= inv_magnitude; x *= inv_magnitude;
y *= inv_magnitude;
} }
float Vector2::sqrMagnitude() const { float Vector2::sqrMagnitude() const
return x * x + y * y; {
return x * x + y * y;
} }
float Vector2::magnitude() const { float Vector2::magnitude() const
return sqrtf(x * x + y * y); {
return sqrtf(x * x + y * y);
} }
Vector2 Vector2::Normalize(const Vector2 &v) { Vector2 Vector2::Normalize(const Vector2& v)
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y); {
return Vector2::Create(v.x * inv_magnitude, v.y * inv_magnitude); float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y);
return Vector2::Create(v.x * inv_magnitude, v.y * inv_magnitude);
} }
float Vector2::Cross(const Vector2 &v1, const Vector2 &v2) { float Vector2::Cross(const Vector2& v1, const Vector2& v2)
return v1.x * v2.y - v1.y * v2.x; {
return v1.x * v2.y - v1.y * v2.x;
} }
float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { float Vector2::Dot(const Vector2& v1, const Vector2& v2)
return v1.x * v2.x + v1.y * v2.y; {
return v1.x * v2.x + v1.y * v2.y;
} }
Vector2 Vector2::Min(const Vector2 &v1, const Vector2 &v2) { Vector2 Vector2::Min(const Vector2& v1, const Vector2& v2)
{
return Vector2::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y)); return Vector2::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y));
} }
Vector2 Vector2::Max(const Vector2 &v1, const Vector2 &v2) { Vector2 Vector2::Max(const Vector2& v1, const Vector2& v2)
{
return Vector2::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y)); return Vector2::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y));
} }

View File

@@ -34,231 +34,262 @@
namespace kraken { namespace kraken {
void Vector2i::init() { void Vector2i::init()
x = 0; {
y = 0; x = 0;
y = 0;
} }
Vector2i Vector2i::Create() Vector2i Vector2i::Create()
{ {
Vector2i r; Vector2i r;
r.init(); r.init();
return r; return r;
} }
void Vector2i::init(int X, int Y) { void Vector2i::init(int X, int Y)
x = X; {
y = Y; x = X;
y = Y;
} }
Vector2i Vector2i::Create(int X, int Y) Vector2i Vector2i::Create(int X, int Y)
{ {
Vector2i r; Vector2i r;
r.init(X,Y); r.init(X, Y);
return r; return r;
} }
void Vector2i::init(int v) { void Vector2i::init(int v)
x = v; {
y = v; x = v;
y = v;
} }
Vector2i Vector2i::Create(int v) Vector2i Vector2i::Create(int v)
{ {
Vector2i r; Vector2i r;
r.init(v); r.init(v);
return r; return r;
} }
void Vector2i::init(int *v) { void Vector2i::init(int* v)
x = v[0];
y = v[1];
}
Vector2i Vector2i::Create(int *v)
{ {
Vector2i r; x = v[0];
r.init(v); y = v[1];
return r;
} }
void Vector2i::init(const Vector2i &v) { Vector2i Vector2i::Create(int* v)
x = v.x;
y = v.y;
}
Vector2i Vector2i::Create(const Vector2i &v)
{ {
Vector2i r; Vector2i r;
r.init(v); r.init(v);
return r; return r;
}
void Vector2i::init(const Vector2i& v)
{
x = v.x;
y = v.y;
}
Vector2i Vector2i::Create(const Vector2i& v)
{
Vector2i r;
r.init(v);
return r;
} }
// Vector2 swizzle getters // Vector2 swizzle getters
Vector2i Vector2i::yx() const Vector2i Vector2i::yx() const
{ {
return Vector2i::Create(y,x); return Vector2i::Create(y, x);
} }
// Vector2 swizzle setters // Vector2 swizzle setters
void Vector2i::yx(const Vector2i &v) void Vector2i::yx(const Vector2i& v)
{ {
y = v.x; y = v.x;
x = v.y; x = v.y;
} }
Vector2i Vector2i::Min() { Vector2i Vector2i::Min()
return Vector2i::Create(-std::numeric_limits<int>::max()); {
return Vector2i::Create(-std::numeric_limits<int>::max());
} }
Vector2i Vector2i::Max() { Vector2i Vector2i::Max()
return Vector2i::Create(std::numeric_limits<int>::max()); {
return Vector2i::Create(std::numeric_limits<int>::max());
} }
Vector2i Vector2i::Zero() { Vector2i Vector2i::Zero()
return Vector2i::Create(0); {
return Vector2i::Create(0);
} }
Vector2i Vector2i::One() { Vector2i Vector2i::One()
return Vector2i::Create(1); {
return Vector2i::Create(1);
} }
Vector2i Vector2i::operator +(const Vector2i& b) const { Vector2i Vector2i::operator +(const Vector2i& b) const
return Vector2i::Create(x + b.x, y + b.y); {
return Vector2i::Create(x + b.x, y + b.y);
} }
Vector2i Vector2i::operator -(const Vector2i& b) const { Vector2i Vector2i::operator -(const Vector2i& b) const
return Vector2i::Create(x - b.x, y - b.y); {
return Vector2i::Create(x - b.x, y - b.y);
} }
Vector2i Vector2i::operator +() const { Vector2i Vector2i::operator +() const
return *this; {
return *this;
} }
Vector2i Vector2i::operator -() const { Vector2i Vector2i::operator -() const
return Vector2i::Create(-x, -y); {
return Vector2i::Create(-x, -y);
} }
Vector2i Vector2i::operator *(const int v) const { Vector2i Vector2i::operator *(const int v) const
return Vector2i::Create(x * v, y * v); {
return Vector2i::Create(x * v, y * v);
} }
Vector2i Vector2i::operator /(const int v) const { Vector2i Vector2i::operator /(const int v) const
return Vector2i::Create(x / v, y / v); {
return Vector2i::Create(x / v, y / v);
} }
Vector2i& Vector2i::operator +=(const Vector2i& b) { Vector2i& Vector2i::operator +=(const Vector2i& b)
x += b.x; {
y += b.y; x += b.x;
return *this; y += b.y;
return *this;
} }
Vector2i& Vector2i::operator -=(const Vector2i& b) { Vector2i& Vector2i::operator -=(const Vector2i& b)
x -= b.x; {
y -= b.y; x -= b.x;
return *this; y -= b.y;
return *this;
} }
Vector2i& Vector2i::operator *=(const int v) { Vector2i& Vector2i::operator *=(const int v)
x *= v; {
y *= v; x *= v;
return *this; y *= v;
return *this;
} }
Vector2i& Vector2i::operator /=(const int v) { Vector2i& Vector2i::operator /=(const int v)
x /= v; {
y /= v; x /= v;
return *this; y /= v;
return *this;
} }
bool Vector2i::operator ==(const Vector2i& b) const { bool Vector2i::operator ==(const Vector2i& b) const
return x == b.x && y == b.y; {
return x == b.x && y == b.y;
} }
bool Vector2i::operator !=(const Vector2i& b) const { bool Vector2i::operator !=(const Vector2i& b) const
return x != b.x || y != b.y; {
return x != b.x || y != b.y;
} }
bool Vector2i::operator >(const Vector2i& b) const bool Vector2i::operator >(const Vector2i& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x > b.x) { if (x > b.x) {
return true; return true;
} else if(x < b.x) { } else if (x < b.x) {
return false; return false;
} else if(y > b.y) { } else if (y > b.y) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool Vector2i::operator <(const Vector2i& b) const bool Vector2i::operator <(const Vector2i& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x < b.x) { if (x < b.x) {
return true; return true;
} else if(x > b.x) { } else if (x > b.x) {
return false; return false;
} else if(y < b.y) { } else if (y < b.y) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
int& Vector2i::operator[] (unsigned i) { int& Vector2i::operator[] (unsigned i)
switch(i) { {
case 0: switch (i) {
return x; case 0:
case 1: return x;
default: case 1:
return y; default:
} return y;
}
} }
int Vector2i::operator[](unsigned i) const { int Vector2i::operator[](unsigned i) const
switch(i) { {
case 0: switch (i) {
return x; case 0:
case 1: return x;
default: case 1:
return y; default:
} return y;
}
} }
void Vector2i::normalize() { void Vector2i::normalize()
int m = magnitude(); {
x /= m; int m = magnitude();
y /= m; x /= m;
y /= m;
} }
int Vector2i::sqrMagnitude() const { int Vector2i::sqrMagnitude() const
return x * x + y * y; {
return x * x + y * y;
} }
int Vector2i::magnitude() const { int Vector2i::magnitude() const
return static_cast<int>(sqrtf((float)x * (float)x + (float)y * (float)y)); {
return static_cast<int>(sqrtf((float)x * (float)x + (float)y * (float)y));
} }
Vector2i Vector2i::Normalize(const Vector2i &v) { Vector2i Vector2i::Normalize(const Vector2i& v)
int m = v.magnitude(); {
return Vector2i::Create(v.x / m, v.y / m); int m = v.magnitude();
return Vector2i::Create(v.x / m, v.y / m);
} }
int Vector2i::Cross(const Vector2i &v1, const Vector2i &v2) { int Vector2i::Cross(const Vector2i& v1, const Vector2i& v2)
return v1.x * v2.y - v1.y * v2.x; {
return v1.x * v2.y - v1.y * v2.x;
} }
int Vector2i::Dot(const Vector2i &v1, const Vector2i &v2) { int Vector2i::Dot(const Vector2i& v1, const Vector2i& v2)
return v1.x * v2.x + v1.y * v2.y; {
return v1.x * v2.x + v1.y * v2.y;
} }
Vector2i Vector2i::Min(const Vector2i &v1, const Vector2i &v2) { Vector2i Vector2i::Min(const Vector2i& v1, const Vector2i& v2)
{
return Vector2i::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y)); return Vector2i::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y));
} }
Vector2i Vector2i::Max(const Vector2i &v1, const Vector2i &v2) { Vector2i Vector2i::Max(const Vector2i& v1, const Vector2i& v2)
{
return Vector2i::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y)); return Vector2i::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y));
} }

View File

@@ -37,428 +37,469 @@ namespace kraken {
//default constructor //default constructor
void Vector3::init() void Vector3::init()
{ {
x = 0.0f; x = 0.0f;
y = 0.0f; y = 0.0f;
z = 0.0f; z = 0.0f;
} }
Vector3 Vector3::Create() Vector3 Vector3::Create()
{ {
Vector3 r; Vector3 r;
r.init(); r.init();
return r; return r;
} }
void Vector3::init(const Vector3 &v) { void Vector3::init(const Vector3& v)
x = v.x;
y = v.y;
z = v.z;
}
Vector3 Vector3::Create(const Vector3 &v)
{ {
Vector3 r; x = v.x;
r.init(v); y = v.y;
return r; z = v.z;
} }
void Vector3::init(const Vector4 &v) { Vector3 Vector3::Create(const Vector3& v)
x = v.x;
y = v.y;
z = v.z;
}
Vector3 Vector3::Create(const Vector4 &v)
{ {
Vector3 r; Vector3 r;
r.init(v); r.init(v);
return r; return r;
} }
void Vector3::init(float *v) { void Vector3::init(const Vector4& v)
x = v[0];
y = v[1];
z = v[2];
}
Vector3 Vector3::Create(float *v)
{ {
Vector3 r; x = v.x;
r.init(v); y = v.y;
return r; z = v.z;
} }
Vector3 Vector3::Create(const Vector4& v)
void Vector3::init(double *v) {
x = (float)v[0];
y = (float)v[1];
z = (float)v[2];
}
Vector3 Vector3::Create(double *v)
{ {
Vector3 r; Vector3 r;
r.init(v); r.init(v);
return r; return r;
}
void Vector3::init(float* v)
{
x = v[0];
y = v[1];
z = v[2];
}
Vector3 Vector3::Create(float* v)
{
Vector3 r;
r.init(v);
return r;
} }
void Vector3::init(float v) { void Vector3::init(double* v)
x = v; {
y = v; x = (float)v[0];
z = v; y = (float)v[1];
z = (float)v[2];
}
Vector3 Vector3::Create(double* v)
{
Vector3 r;
r.init(v);
return r;
}
void Vector3::init(float v)
{
x = v;
y = v;
z = v;
} }
Vector3 Vector3::Create(float v) Vector3 Vector3::Create(float v)
{ {
Vector3 r; Vector3 r;
r.init(v); r.init(v);
return r; return r;
} }
void Vector3::init(float X, float Y, float Z) void Vector3::init(float X, float Y, float Z)
{ {
x = X; x = X;
y = Y; y = Y;
z = Z; z = Z;
} }
Vector3 Vector3::Create(float X, float Y, float Z) Vector3 Vector3::Create(float X, float Y, float Z)
{ {
Vector3 r; Vector3 r;
r.init(X,Y,Z); r.init(X, Y, Z);
return r; return r;
} }
Vector2 Vector3::xx() const Vector2 Vector3::xx() const
{ {
return Vector2::Create(x,x); return Vector2::Create(x, x);
} }
Vector2 Vector3::xy() const Vector2 Vector3::xy() const
{ {
return Vector2::Create(x,y); return Vector2::Create(x, y);
} }
Vector2 Vector3::xz() const Vector2 Vector3::xz() const
{ {
return Vector2::Create(x,z); return Vector2::Create(x, z);
} }
Vector2 Vector3::yx() const Vector2 Vector3::yx() const
{ {
return Vector2::Create(y,x); return Vector2::Create(y, x);
} }
Vector2 Vector3::yy() const Vector2 Vector3::yy() const
{ {
return Vector2::Create(y,y); return Vector2::Create(y, y);
} }
Vector2 Vector3::yz() const Vector2 Vector3::yz() const
{ {
return Vector2::Create(y,z); return Vector2::Create(y, z);
} }
Vector2 Vector3::zx() const Vector2 Vector3::zx() const
{ {
return Vector2::Create(z,x); return Vector2::Create(z, x);
} }
Vector2 Vector3::zy() const Vector2 Vector3::zy() const
{ {
return Vector2::Create(z,y); return Vector2::Create(z, y);
} }
Vector2 Vector3::zz() const Vector2 Vector3::zz() const
{ {
return Vector2::Create(z,z); return Vector2::Create(z, z);
} }
void Vector3::xy(const Vector2 &v) void Vector3::xy(const Vector2& v)
{ {
x = v.x; x = v.x;
y = v.y; y = v.y;
} }
void Vector3::xz(const Vector2 &v) void Vector3::xz(const Vector2& v)
{ {
x = v.x; x = v.x;
z = v.y; z = v.y;
} }
void Vector3::yx(const Vector2 &v) void Vector3::yx(const Vector2& v)
{ {
y = v.x; y = v.x;
x = v.y; x = v.y;
} }
void Vector3::yz(const Vector2 &v) void Vector3::yz(const Vector2& v)
{ {
y = v.x; y = v.x;
z = v.y; z = v.y;
} }
void Vector3::zx(const Vector2 &v) void Vector3::zx(const Vector2& v)
{ {
z = v.x; z = v.x;
x = v.y; x = v.y;
} }
void Vector3::zy(const Vector2 &v) void Vector3::zy(const Vector2& v)
{ {
z = v.x; z = v.x;
y = v.y; y = v.y;
} }
Vector3 Vector3::Min() { Vector3 Vector3::Min()
return Vector3::Create(-std::numeric_limits<float>::max());
}
Vector3 Vector3::Max() {
return Vector3::Create(std::numeric_limits<float>::max());
}
Vector3 Vector3::Zero() {
return Vector3::Create();
}
Vector3 Vector3::One() {
return Vector3::Create(1.0f, 1.0f, 1.0f);
}
Vector3 Vector3::Forward() {
return Vector3::Create(0.0f, 0.0f, 1.0f);
}
Vector3 Vector3::Backward() {
return Vector3::Create(0.0f, 0.0f, -1.0f);
}
Vector3 Vector3::Up() {
return Vector3::Create(0.0f, 1.0f, 0.0f);
}
Vector3 Vector3::Down() {
return Vector3::Create(0.0f, -1.0f, 0.0f);
}
Vector3 Vector3::Left() {
return Vector3::Create(-1.0f, 0.0f, 0.0f);
}
Vector3 Vector3::Right() {
return Vector3::Create(1.0f, 0.0f, 0.0f);
}
void Vector3::scale(const Vector3 &v)
{ {
x *= v.x; return Vector3::Create(-std::numeric_limits<float>::max());
y *= v.y;
z *= v.z;
} }
Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) Vector3 Vector3::Max()
{ {
return Vector3::Create(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); return Vector3::Create(std::numeric_limits<float>::max());
} }
Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float d) { Vector3 Vector3::Zero()
return v1 + (v2 - v1) * d; {
return Vector3::Create();
} }
Vector3 Vector3::Slerp(const Vector3 &v1, const Vector3 &v2, float d) { Vector3 Vector3::One()
// From: http://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/ {
// Dot product - the cosine of the angle between 2 vectors. return Vector3::Create(1.0f, 1.0f, 1.0f);
float dot = Vector3::Dot(v1, v2);
// Clamp it to be in the range of Acos()
if(dot < -1.0f) dot = -1.0f;
if(dot > 1.0f) dot = 1.0f;
// Acos(dot) returns the angle between start and end,
// And multiplying that by percent returns the angle between
// start and the final result.
float theta = acosf(dot)*d;
Vector3 RelativeVec = v2 - v1*dot;
RelativeVec.normalize(); // Orthonormal basis
// The final result.
return ((v1*cosf(theta)) + (RelativeVec*sinf(theta)));
} }
void Vector3::OrthoNormalize(Vector3 &normal, Vector3 &tangent) { Vector3 Vector3::Forward()
// Gram-Schmidt Orthonormalization {
normal.normalize(); return Vector3::Create(0.0f, 0.0f, 1.0f);
Vector3 proj = normal * Dot(tangent, normal);
tangent = tangent - proj;
tangent.normalize();
} }
Vector3& Vector3::operator =(const Vector4 &b) { Vector3 Vector3::Backward()
x = b.x; {
y = b.y; return Vector3::Create(0.0f, 0.0f, -1.0f);
z = b.z;
return *this;
} }
Vector3 Vector3::operator +(const Vector3& b) const { Vector3 Vector3::Up()
return Vector3::Create(x + b.x, y + b.y, z + b.z); {
} return Vector3::Create(0.0f, 1.0f, 0.0f);
Vector3 Vector3::operator -(const Vector3& b) const {
return Vector3::Create(x - b.x, y - b.y, z - b.z);
}
Vector3 Vector3::operator +() const {
return *this;
}
Vector3 Vector3::operator -() const {
return Vector3::Create(-x, -y, -z);
} }
Vector3 Vector3::operator *(const float v) const { Vector3 Vector3::Down()
return Vector3::Create(x * v, y * v, z * v); {
return Vector3::Create(0.0f, -1.0f, 0.0f);
} }
Vector3 Vector3::operator /(const float v) const { Vector3 Vector3::Left()
float inv_v = 1.0f / v; {
return Vector3::Create(x * inv_v, y * inv_v, z * inv_v); return Vector3::Create(-1.0f, 0.0f, 0.0f);
} }
Vector3& Vector3::operator +=(const Vector3& b) { Vector3 Vector3::Right()
x += b.x; {
y += b.y; return Vector3::Create(1.0f, 0.0f, 0.0f);
z += b.z;
return *this;
} }
Vector3& Vector3::operator -=(const Vector3& b) {
x -= b.x; void Vector3::scale(const Vector3& v)
y -= b.y; {
z -= b.z; x *= v.x;
y *= v.y;
return *this; z *= v.z;
} }
Vector3& Vector3::operator *=(const float v) { Vector3 Vector3::Scale(const Vector3& v1, const Vector3& v2)
x *= v; {
y *= v; return Vector3::Create(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
z *= v;
return *this;
} }
Vector3& Vector3::operator /=(const float v) { Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float d)
float inv_v = 1.0f / v; {
x *= inv_v; return v1 + (v2 - v1) * d;
y *= inv_v;
z *= inv_v;
return *this;
} }
bool Vector3::operator ==(const Vector3& b) const { Vector3 Vector3::Slerp(const Vector3& v1, const Vector3& v2, float d)
return x == b.x && y == b.y && z == b.z; {
// From: http://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/
} // Dot product - the cosine of the angle between 2 vectors.
bool Vector3::operator !=(const Vector3& b) const { float dot = Vector3::Dot(v1, v2);
return x != b.x || y != b.y || z != b.z; // Clamp it to be in the range of Acos()
if (dot < -1.0f) dot = -1.0f;
if (dot > 1.0f) dot = 1.0f;
// Acos(dot) returns the angle between start and end,
// And multiplying that by percent returns the angle between
// start and the final result.
float theta = acosf(dot) * d;
Vector3 RelativeVec = v2 - v1 * dot;
RelativeVec.normalize(); // Orthonormal basis
// The final result.
return ((v1 * cosf(theta)) + (RelativeVec * sinf(theta)));
} }
float& Vector3::operator[](unsigned i) { void Vector3::OrthoNormalize(Vector3& normal, Vector3& tangent)
switch(i) { {
case 0: // Gram-Schmidt Orthonormalization
return x; normal.normalize();
case 1: Vector3 proj = normal * Dot(tangent, normal);
return y; tangent = tangent - proj;
default: tangent.normalize();
case 2:
return z;
}
} }
float Vector3::operator[](unsigned i) const { Vector3& Vector3::operator =(const Vector4& b)
switch(i) { {
case 0: x = b.x;
return x; y = b.y;
case 1: z = b.z;
return y; return *this;
case 2:
default:
return z;
}
} }
float Vector3::sqrMagnitude() const { Vector3 Vector3::operator +(const Vector3& b) const
// calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function) {
return x * x + y * y + z * z; return Vector3::Create(x + b.x, y + b.y, z + b.z);
}
Vector3 Vector3::operator -(const Vector3& b) const
{
return Vector3::Create(x - b.x, y - b.y, z - b.z);
}
Vector3 Vector3::operator +() const
{
return *this;
}
Vector3 Vector3::operator -() const
{
return Vector3::Create(-x, -y, -z);
} }
float Vector3::magnitude() const { Vector3 Vector3::operator *(const float v) const
return sqrtf(x * x + y * y + z * z); {
return Vector3::Create(x * v, y * v, z * v);
} }
void Vector3::normalize() { Vector3 Vector3::operator /(const float v) const
float inv_magnitude = 1.0f / sqrtf(x * x + y * y + z * z); {
x *= inv_magnitude; float inv_v = 1.0f / v;
y *= inv_magnitude; return Vector3::Create(x * inv_v, y * inv_v, z * inv_v);
z *= inv_magnitude;
}
Vector3 Vector3::Normalize(const Vector3 &v) {
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
return Vector3::Create(v.x * inv_magnitude, v.y * inv_magnitude, v.z * inv_magnitude);
} }
Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { Vector3& Vector3::operator +=(const Vector3& b)
return Vector3::Create(v1.y * v2.z - v1.z * v2.y, {
v1.z * v2.x - v1.x * v2.z, x += b.x;
v1.x * v2.y - v1.y * v2.x); y += b.y;
z += b.z;
return *this;
} }
float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) { Vector3& Vector3::operator -=(const Vector3& b)
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; {
x -= b.x;
y -= b.y;
z -= b.z;
return *this;
} }
Vector3 Vector3::Min(const Vector3 &v1, const Vector3 &v2) { Vector3& Vector3::operator *=(const float v)
{
x *= v;
y *= v;
z *= v;
return *this;
}
Vector3& Vector3::operator /=(const float v)
{
float inv_v = 1.0f / v;
x *= inv_v;
y *= inv_v;
z *= inv_v;
return *this;
}
bool Vector3::operator ==(const Vector3& b) const
{
return x == b.x && y == b.y && z == b.z;
}
bool Vector3::operator !=(const Vector3& b) const
{
return x != b.x || y != b.y || z != b.z;
}
float& Vector3::operator[](unsigned i)
{
switch (i) {
case 0:
return x;
case 1:
return y;
default:
case 2:
return z;
}
}
float Vector3::operator[](unsigned i) const
{
switch (i) {
case 0:
return x;
case 1:
return y;
case 2:
default:
return z;
}
}
float Vector3::sqrMagnitude() const
{
// calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
return x * x + y * y + z * z;
}
float Vector3::magnitude() const
{
return sqrtf(x * x + y * y + z * z);
}
void Vector3::normalize()
{
float inv_magnitude = 1.0f / sqrtf(x * x + y * y + z * z);
x *= inv_magnitude;
y *= inv_magnitude;
z *= inv_magnitude;
}
Vector3 Vector3::Normalize(const Vector3& v)
{
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
return Vector3::Create(v.x * inv_magnitude, v.y * inv_magnitude, v.z * inv_magnitude);
}
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2)
{
return Vector3::Create(v1.y * v2.z - v1.z * v2.y,
v1.z * v2.x - v1.x * v2.z,
v1.x * v2.y - v1.y * v2.x);
}
float Vector3::Dot(const Vector3& v1, const Vector3& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
Vector3 Vector3::Min(const Vector3& v1, const Vector3& v2)
{
return Vector3::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y), KRMIN(v1.z, v2.z)); return Vector3::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y), KRMIN(v1.z, v2.z));
} }
Vector3 Vector3::Max(const Vector3 &v1, const Vector3 &v2) { Vector3 Vector3::Max(const Vector3& v1, const Vector3& v2)
{
return Vector3::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y), KRMAX(v1.z, v2.z)); return Vector3::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y), KRMAX(v1.z, v2.z));
} }
bool Vector3::operator >(const Vector3& b) const bool Vector3::operator >(const Vector3& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x > b.x) { if (x > b.x) {
return true; return true;
} else if(x < b.x) { } else if (x < b.x) {
return false; return false;
} else if(y > b.y) { } else if (y > b.y) {
return true; return true;
} else if(y < b.y) { } else if (y < b.y) {
return false; return false;
} else if(z > b.z) { } else if (z > b.z) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool Vector3::operator <(const Vector3& b) const bool Vector3::operator <(const Vector3& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x < b.x) { if (x < b.x) {
return true; return true;
} else if(x > b.x) { } else if (x > b.x) {
return false; return false;
} else if(y < b.y) { } else if (y < b.y) {
return true; return true;
} else if(y > b.y) { } else if (y > b.y) {
return false; return false;
} else if(z < b.z) { } else if (z < b.z) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
} // namespace kraken } // namespace kraken

View File

@@ -37,308 +37,346 @@ namespace kraken {
//default constructor //default constructor
void Vector4::init() void Vector4::init()
{ {
x = 0.0f; x = 0.0f;
y = 0.0f; y = 0.0f;
z = 0.0f; z = 0.0f;
w = 0.0f; w = 0.0f;
} }
Vector4 Vector4::Create() Vector4 Vector4::Create()
{ {
Vector4 r; Vector4 r;
r.init(); r.init();
return r; return r;
} }
void Vector4::init(const Vector4 &v) { void Vector4::init(const Vector4& v)
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
Vector4 Vector4::Create(const Vector4 &v)
{ {
Vector4 r; x = v.x;
r.init(v); y = v.y;
return r; z = v.z;
w = v.w;
} }
void Vector4::init(const Vector3 &v, float W) { Vector4 Vector4::Create(const Vector4& v)
x = v.x;
y = v.y;
z = v.z;
w = W;
}
Vector4 Vector4::Create(const Vector3 &v, float W)
{ {
Vector4 r; Vector4 r;
r.init(v, W); r.init(v);
return r; return r;
} }
void Vector4::init(float *v) { void Vector4::init(const Vector3& v, float W)
x = v[0];
y = v[1];
z = v[2];
w = v[3];
}
Vector4 Vector4::Create(float *v)
{ {
Vector4 r; x = v.x;
r.init(v); y = v.y;
return r; z = v.z;
w = W;
} }
void Vector4::init(float v) { Vector4 Vector4::Create(const Vector3& v, float W)
x = v; {
y = v; Vector4 r;
z = v; r.init(v, W);
w = v; return r;
}
void Vector4::init(float* v)
{
x = v[0];
y = v[1];
z = v[2];
w = v[3];
}
Vector4 Vector4::Create(float* v)
{
Vector4 r;
r.init(v);
return r;
}
void Vector4::init(float v)
{
x = v;
y = v;
z = v;
w = v;
} }
Vector4 Vector4::Create(float v) Vector4 Vector4::Create(float v)
{ {
Vector4 r; Vector4 r;
r.init(v); r.init(v);
return r; return r;
} }
void Vector4::init(float X, float Y, float Z, float W) void Vector4::init(float X, float Y, float Z, float W)
{ {
x = X; x = X;
y = Y; y = Y;
z = Z; z = Z;
w = W; w = W;
} }
Vector4 Vector4::Create(float X, float Y, float Z, float W) Vector4 Vector4::Create(float X, float Y, float Z, float W)
{ {
Vector4 r; Vector4 r;
r.init(X, Y, Z, W); r.init(X, Y, Z, W);
return r; return r;
} }
Vector4 Vector4::Min() { Vector4 Vector4::Min()
return Vector4::Create(-std::numeric_limits<float>::max()); {
return Vector4::Create(-std::numeric_limits<float>::max());
} }
Vector4 Vector4::Max() { Vector4 Vector4::Max()
return Vector4::Create(std::numeric_limits<float>::max()); {
return Vector4::Create(std::numeric_limits<float>::max());
} }
Vector4 Vector4::Zero() { Vector4 Vector4::Zero()
return Vector4::Create(); {
return Vector4::Create();
} }
Vector4 Vector4::One() { Vector4 Vector4::One()
return Vector4::Create(1.0f, 1.0f, 1.0f, 1.0f); {
return Vector4::Create(1.0f, 1.0f, 1.0f, 1.0f);
} }
Vector4 Vector4::Forward() { Vector4 Vector4::Forward()
return Vector4::Create(0.0f, 0.0f, 1.0f, 1.0f); {
return Vector4::Create(0.0f, 0.0f, 1.0f, 1.0f);
} }
Vector4 Vector4::Backward() { Vector4 Vector4::Backward()
return Vector4::Create(0.0f, 0.0f, -1.0f, 1.0f); {
return Vector4::Create(0.0f, 0.0f, -1.0f, 1.0f);
} }
Vector4 Vector4::Up() { Vector4 Vector4::Up()
return Vector4::Create(0.0f, 1.0f, 0.0f, 1.0f); {
return Vector4::Create(0.0f, 1.0f, 0.0f, 1.0f);
} }
Vector4 Vector4::Down() { Vector4 Vector4::Down()
return Vector4::Create(0.0f, -1.0f, 0.0f, 1.0f); {
return Vector4::Create(0.0f, -1.0f, 0.0f, 1.0f);
} }
Vector4 Vector4::Left() { Vector4 Vector4::Left()
return Vector4::Create(-1.0f, 0.0f, 0.0f, 1.0f); {
return Vector4::Create(-1.0f, 0.0f, 0.0f, 1.0f);
} }
Vector4 Vector4::Right() { Vector4 Vector4::Right()
return Vector4::Create(1.0f, 0.0f, 0.0f, 1.0f); {
return Vector4::Create(1.0f, 0.0f, 0.0f, 1.0f);
} }
Vector4 Vector4::Lerp(const Vector4 &v1, const Vector4 &v2, float d) { Vector4 Vector4::Lerp(const Vector4& v1, const Vector4& v2, float d)
return v1 + (v2 - v1) * d; {
return v1 + (v2 - v1) * d;
} }
Vector4 Vector4::Slerp(const Vector4 &v1, const Vector4 &v2, float d) { Vector4 Vector4::Slerp(const Vector4& v1, const Vector4& v2, float d)
// From: http://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/ {
// Dot product - the cosine of the angle between 2 vectors. // From: http://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/
float dot = Vector4::Dot(v1, v2); // Dot product - the cosine of the angle between 2 vectors.
// Clamp it to be in the range of Acos() float dot = Vector4::Dot(v1, v2);
if(dot < -1.0f) dot = -1.0f; // Clamp it to be in the range of Acos()
if(dot > 1.0f) dot = 1.0f; if (dot < -1.0f) dot = -1.0f;
// Acos(dot) returns the angle between start and end, if (dot > 1.0f) dot = 1.0f;
// And multiplying that by percent returns the angle between // Acos(dot) returns the angle between start and end,
// start and the final result. // And multiplying that by percent returns the angle between
float theta = acosf(dot)*d; // start and the final result.
Vector4 RelativeVec = v2 - v1*dot; float theta = acosf(dot) * d;
RelativeVec.normalize(); // Orthonormal basis Vector4 RelativeVec = v2 - v1 * dot;
// The final result. RelativeVec.normalize(); // Orthonormal basis
return ((v1*cosf(theta)) + (RelativeVec*sinf(theta))); // The final result.
return ((v1 * cosf(theta)) + (RelativeVec * sinf(theta)));
} }
void Vector4::OrthoNormalize(Vector4 &normal, Vector4 &tangent) { void Vector4::OrthoNormalize(Vector4& normal, Vector4& tangent)
// Gram-Schmidt Orthonormalization {
normal.normalize(); // Gram-Schmidt Orthonormalization
Vector4 proj = normal * Dot(tangent, normal); normal.normalize();
tangent = tangent - proj; Vector4 proj = normal * Dot(tangent, normal);
tangent.normalize(); tangent = tangent - proj;
tangent.normalize();
} }
Vector4 Vector4::operator +(const Vector4& b) const { Vector4 Vector4::operator +(const Vector4& b) const
return Vector4::Create(x + b.x, y + b.y, z + b.z, w + b.w); {
return Vector4::Create(x + b.x, y + b.y, z + b.z, w + b.w);
} }
Vector4 Vector4::operator -(const Vector4& b) const { Vector4 Vector4::operator -(const Vector4& b) const
return Vector4::Create(x - b.x, y - b.y, z - b.z, w - b.w); {
return Vector4::Create(x - b.x, y - b.y, z - b.z, w - b.w);
} }
Vector4 Vector4::operator +() const { Vector4 Vector4::operator +() const
return *this; {
return *this;
} }
Vector4 Vector4::operator -() const { Vector4 Vector4::operator -() const
return Vector4::Create(-x, -y, -z, -w); {
return Vector4::Create(-x, -y, -z, -w);
} }
Vector4 Vector4::operator *(const float v) const { Vector4 Vector4::operator *(const float v) const
return Vector4::Create(x * v, y * v, z * v, w * v); {
return Vector4::Create(x * v, y * v, z * v, w * v);
} }
Vector4 Vector4::operator /(const float v) const { Vector4 Vector4::operator /(const float v) const
return Vector4::Create(x / v, y / v, z / v, w/ v); {
return Vector4::Create(x / v, y / v, z / v, w / v);
} }
Vector4& Vector4::operator +=(const Vector4& b) { Vector4& Vector4::operator +=(const Vector4& b)
x += b.x; {
y += b.y; x += b.x;
z += b.z; y += b.y;
w += b.w; z += b.z;
w += b.w;
return *this;
return *this;
} }
Vector4& Vector4::operator -=(const Vector4& b) { Vector4& Vector4::operator -=(const Vector4& b)
x -= b.x; {
y -= b.y; x -= b.x;
z -= b.z; y -= b.y;
w -= b.w; z -= b.z;
w -= b.w;
return *this;
return *this;
} }
Vector4& Vector4::operator *=(const float v) { Vector4& Vector4::operator *=(const float v)
x *= v; {
y *= v; x *= v;
z *= v; y *= v;
w *= v; z *= v;
w *= v;
return *this;
return *this;
} }
Vector4& Vector4::operator /=(const float v) { Vector4& Vector4::operator /=(const float v)
float inv_v = 1.0f / v; {
x *= inv_v; float inv_v = 1.0f / v;
y *= inv_v; x *= inv_v;
z *= inv_v; y *= inv_v;
w *= inv_v; z *= inv_v;
w *= inv_v;
return *this;
return *this;
} }
bool Vector4::operator ==(const Vector4& b) const { bool Vector4::operator ==(const Vector4& b) const
return x == b.x && y == b.y && z == b.z && w == b.w; {
return x == b.x && y == b.y && z == b.z && w == b.w;
} }
bool Vector4::operator !=(const Vector4& b) const { bool Vector4::operator !=(const Vector4& b) const
return x != b.x || y != b.y || z != b.z || w != b.w; {
return x != b.x || y != b.y || z != b.z || w != b.w;
} }
float& Vector4::operator[](unsigned i) { float& Vector4::operator[](unsigned i)
switch(i) { {
case 0: switch (i) {
return x; case 0:
case 1: return x;
return y; case 1:
case 2: return y;
return z; case 2:
default: return z;
case 3: default:
return w; case 3:
} return w;
}
} }
float Vector4::operator[](unsigned i) const { float Vector4::operator[](unsigned i) const
switch(i) { {
case 0: switch (i) {
return x; case 0:
case 1: return x;
return y; case 1:
case 2: return y;
return z; case 2:
default: return z;
case 3: default:
return w; case 3:
} return w;
}
} }
float Vector4::sqrMagnitude() const { float Vector4::sqrMagnitude() const
// calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function) {
return x * x + y * y + z * z + w * w; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
return x * x + y * y + z * z + w * w;
} }
float Vector4::magnitude() const { float Vector4::magnitude() const
return sqrtf(x * x + y * y + z * z + w * w); {
return sqrtf(x * x + y * y + z * z + w * w);
} }
void Vector4::normalize() { void Vector4::normalize()
float inv_magnitude = 1.0f / sqrtf(x * x + y * y + z * z + w * w); {
x *= inv_magnitude; float inv_magnitude = 1.0f / sqrtf(x * x + y * y + z * z + w * w);
y *= inv_magnitude; x *= inv_magnitude;
z *= inv_magnitude; y *= inv_magnitude;
w *= inv_magnitude; z *= inv_magnitude;
w *= inv_magnitude;
} }
Vector4 Vector4::Normalize(const Vector4 &v) { Vector4 Vector4::Normalize(const Vector4& v)
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w); {
return Vector4::Create(v.x * inv_magnitude, float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
v.y * inv_magnitude, return Vector4::Create(v.x * inv_magnitude,
v.z * inv_magnitude, v.y * inv_magnitude,
v.w * inv_magnitude); v.z * inv_magnitude,
v.w * inv_magnitude);
} }
float Vector4::Dot(const Vector4 &v1, const Vector4 &v2) { float Vector4::Dot(const Vector4& v1, const Vector4& v2)
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w; {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
} }
Vector4 Vector4::Min(const Vector4 &v1, const Vector4 &v2) { Vector4 Vector4::Min(const Vector4& v1, const Vector4& v2)
{
return Vector4::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y), KRMIN(v1.z, v2.z), KRMIN(v1.w, v2.w)); return Vector4::Create(KRMIN(v1.x, v2.x), KRMIN(v1.y, v2.y), KRMIN(v1.z, v2.z), KRMIN(v1.w, v2.w));
} }
Vector4 Vector4::Max(const Vector4 &v1, const Vector4 &v2) { Vector4 Vector4::Max(const Vector4& v1, const Vector4& v2)
{
return Vector4::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y), KRMAX(v1.z, v2.z), KRMAX(v1.w, v2.w)); return Vector4::Create(KRMAX(v1.x, v2.x), KRMAX(v1.y, v2.y), KRMAX(v1.z, v2.z), KRMAX(v1.w, v2.w));
} }
bool Vector4::operator >(const Vector4& b) const bool Vector4::operator >(const Vector4& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x != b.x) return x > b.x; if (x != b.x) return x > b.x;
if(y != b.y) return y > b.y; if (y != b.y) return y > b.y;
if(z != b.z) return z > b.z; if (z != b.z) return z > b.z;
if(w != b.w) return w > b.w; if (w != b.w) return w > b.w;
return false; return false;
} }
bool Vector4::operator <(const Vector4& b) const bool Vector4::operator <(const Vector4& b) const
{ {
// Comparison operators are implemented to allow insertion into sorted containers such as std::set // Comparison operators are implemented to allow insertion into sorted containers such as std::set
if(x != b.x) return x < b.x; if (x != b.x) return x < b.x;
if(y != b.y) return y < b.y; if (y != b.y) return y < b.y;
if(z != b.z) return z < b.z; if (z != b.z) return z < b.z;
if(w != b.w) return w < b.w; if (w != b.w) return w < b.w;
return false; return false;
} }
} // namespace kraken } // namespace kraken