Structs continued

dev-ui
Piotr Dziwinski 2012-04-29 23:21:35 +02:00
parent b5b9fdb680
commit 7369b10a87
7 changed files with 750 additions and 103 deletions

View File

@ -40,5 +40,5 @@ namespace Math
//! Degrees to radians multiplier
const float DEG_TO_RAD = 0.01745329251994329547f;
//! Radians to degrees multiplier
const FLOAT RAD_TO_DEG = 57.29577951308232286465f;
const float RAD_TO_DEG = 57.29577951308232286465f;
};

View File

@ -21,6 +21,7 @@
#pragma once
#include "const.h"
#include "point.h"
#include <cmath>
#include <cstdlib>
@ -28,10 +29,16 @@
namespace Math
{
//! Compares a and b within TOLERANCE
bool IsEqual(float a, float b)
//! Compares \a a and \a b within \a tolerance
inline bool IsEqual(float a, float b, float tolerance = Math::TOLERANCE)
{
return Abs(a - b) < TOLERANCE;
return fabs(a - b) < tolerance;
}
//! Compares \a a to zero within \a tolerance
inline bool IsZero(float a, float tolerance = Math::TOLERANCE)
{
return IsEqual(a, 0.0f, tolerance);
}
//! Minimum
@ -86,12 +93,6 @@ inline float Norm(float a)
return a;
}
//! Returns the absolute value
inline float Abs(float a)
{
return (float)std::fabs(a);
}
//! Swaps two integers
inline void Swap(int &a, int &b)
{
@ -188,7 +189,7 @@ inline float Rand()
out: -1 0 0 1 */
float Neutral(float value, float dead)
{
if ( Abs(value) <= dead )
if ( fabs(value) <= dead )
{
return 0.0f;
}
@ -252,3 +253,6 @@ inline float Bounce(float progress, float middle, float bounce)
return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*PI)*(bounce/2.0f);
}
}
}; // namespace Math

View File

@ -21,8 +21,11 @@
#pragma once
#include "const.h"
#include "func.h"
#include "vector.h"
#include <cmath>
#include <cassert>
// Math module namespace
namespace Math
@ -33,6 +36,18 @@ namespace Math
Represents an universal 4x4 matrix that can be used in OpenGL and DirectX engines.
Contains the required methods for operating on matrices (inverting, multiplying, etc.).
The internal representation is a 16-value table in column-major order, thus:
m[0 ] m[4 ] m[8 ] m[12]
m[1 ] m[5 ] m[9 ] m[13]
m[2 ] m[6 ] m[10] m[14]
m[3 ] m[7 ] m[11] m[15]
This representation is native to OpenGL; DirectX requires transposing the matrix.
The order of multiplication of matrix and vector is also OpenGL-native
(see the method Vector::MultiplyMatrix).
All methods are made inline to maximize optimization.
TODO test
@ -40,7 +55,7 @@ namespace Math
**/
struct Matrix
{
//! Matrix values in row-major format
//! Matrix values in column-major format
float m[16];
//! Creates the indentity matrix
@ -50,10 +65,11 @@ struct Matrix
}
//! Creates the matrix from given values
/** \a m values in row-major format */
inline Matrix(float m[16])
/** \a m values in column-major format */
inline Matrix(const float (&m)[16])
{
this->m = m;
for (int i = 0; i < 16; ++i)
this->m[i] = m[i];
}
//! Loads the zero matrix
@ -70,20 +86,8 @@ struct Matrix
m[0] = m[5] = m[10] = m[15] = 1.0f;
}
//! Calculates the determinant of the matrix
/** \returns the determinant */
float Det() const
{
float result = 0.0f;
for (int i = 0; i < 4; ++i)
{
result += m[0][i] * Cofactor(0, i);
}
return result;
}
//! Transposes the matrix
void Transpose()
inline void Transpose()
{
Matrix temp = *this;
for (int r = 0; r < 4; ++r)
@ -95,37 +99,197 @@ struct Matrix
}
}
//! Calculates the determinant of the matrix
/** \returns the determinant */
inline float Det() const
{
float result = 0.0f;
for (int i = 0; i < 4; ++i)
{
result += m[i] * Cofactor(i, 0);
}
return result;
}
//! Calculates the cofactor of the matrix
/** \a r row (0 to 3)
\a c column (0 to 3)
\returns the cofactor or 0.0f if invalid r, c given*/
float Cofactor(int r, int c) const
inline float Cofactor(int r, int c) const
{
if ((r < 0) || (r > 3) || (c < 0) || (c > 3))
return 0.0f;
assert(r >= 0 && r <= 3);
assert(c >= 0 && c <= 3);
float tab[3][3];
int tabR = 0;
for (int r = 0; r < 4; ++r)
float result = 0.0f;
/* That looks horrible, I know. But it's fast :) */
switch (4*r + c)
{
if (r == i) continue;
int tabC = 0;
for (int c = 0; c < 4; ++c)
{
if (c == j) continue;
tab[tabR][tabC] = m[4*r + c];
++tabC;
}
++tabR;
// r=0, c=0
/* 05 09 13
06 10 14
07 11 15 */
case 0:
result = + m[5 ] * (m[10] * m[15] - m[14] * m[11])
- m[9 ] * (m[6 ] * m[15] - m[14] * m[7 ])
+ m[13] * (m[6 ] * m[11] - m[10] * m[7 ]);
break;
// r=0, c=1
/* 01 09 13
02 10 14
03 11 15 */
case 1:
result = - m[1 ] * (m[10] * m[15] - m[14] * m[11])
+ m[9 ] * (m[2 ] * m[15] - m[14] * m[3 ])
- m[13] * (m[2 ] * m[11] - m[10] * m[3 ]);
break;
// r=0, c=2
/* 01 05 13
02 06 14
03 07 15 */
case 2:
result = + m[1 ] * (m[6 ] * m[15] - m[14] * m[7 ])
- m[5 ] * (m[2 ] * m[15] - m[14] * m[3 ])
+ m[13] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
break;
// r=0, c=3
/* 01 05 09
02 06 10
03 07 11 */
case 3:
result = - m[1 ] * (m[6 ] * m[11] - m[10] * m[7 ])
+ m[5 ] * (m[2 ] * m[11] - m[10] * m[3 ])
- m[9 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
break;
// r=1, c=0
/* 04 08 12
06 10 14
07 11 15 */
case 4:
result = - m[4 ] * (m[10] * m[15] - m[14] * m[11])
+ m[8 ] * (m[6 ] * m[15] - m[14] * m[7 ])
- m[12] * (m[6 ] * m[11] - m[10] * m[7 ]);
break;
// r=1, c=1
/* 00 08 12
02 10 14
03 11 15 */
case 5:
result = + m[0 ] * (m[10] * m[15] - m[14] * m[11])
- m[8 ] * (m[2 ] * m[15] - m[14] * m[3 ])
+ m[12] * (m[2 ] * m[11] - m[10] * m[3 ]);
break;
// r=1, c=2
/* 00 04 12
02 06 14
03 07 15 */
case 6:
result = - m[0 ] * (m[6 ] * m[15] - m[14] * m[7 ])
+ m[4 ] * (m[2 ] * m[15] - m[14] * m[3 ])
- m[12] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
break;
// r=1, c=3
/* 00 04 08
02 06 10
03 07 11 */
case 7:
result = + m[0 ] * (m[6 ] * m[11] - m[10] * m[7 ])
- m[4 ] * (m[2 ] * m[11] - m[10] * m[3 ])
+ m[8 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
break;
// r=2, c=0
/* 04 08 12
05 09 13
07 11 15 */
case 8:
result = + m[4 ] * (m[9 ] * m[15] - m[13] * m[11])
- m[8 ] * (m[5 ] * m[15] - m[13] * m[7 ])
+ m[12] * (m[5 ] * m[11] - m[9 ] * m[7 ]);
break;
// r=2, c=1
/* 00 08 12
01 09 13
03 11 15 */
case 9:
result = - m[0 ] * (m[9 ] * m[15] - m[13] * m[11])
+ m[8 ] * (m[1 ] * m[15] - m[13] * m[3 ])
- m[12] * (m[1 ] * m[11] - m[9 ] * m[3 ]);
break;
// r=2, c=2
/* 00 04 12
01 05 13
03 07 15 */
case 10:
result = + m[0 ] * (m[5 ] * m[15] - m[13] * m[7 ])
- m[4 ] * (m[1 ] * m[15] - m[13] * m[3 ])
+ m[12] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]);
break;
// r=2, c=3
/* 00 04 08
01 05 09
03 07 11 */
case 11:
result = - m[0 ] * (m[5 ] * m[11] - m[9 ] * m[7 ])
+ m[4 ] * (m[1 ] * m[11] - m[9 ] * m[3 ])
- m[8 ] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]);
break;
// r=3, c=0
/* 04 08 12
05 09 13
06 10 14 */
case 12:
result = - m[4 ] * (m[9 ] * m[14] - m[13] * m[10])
+ m[8 ] * (m[5 ] * m[14] - m[13] * m[6 ])
- m[12] * (m[5 ] * m[10] - m[9 ] * m[6 ]);
break;
// r=3, c=1
/* 00 08 12
01 09 13
02 10 14 */
case 13:
result = + m[0 ] * (m[9 ] * m[14] - m[13] * m[10])
- m[8 ] * (m[1 ] * m[14] - m[13] * m[2 ])
+ m[12] * (m[1 ] * m[10] - m[9 ] * m[2 ]);
break;
// r=3, c=2
/* 00 04 12
01 05 13
02 06 14 */
case 14:
result = - m[0 ] * (m[5 ] * m[14] - m[13] * m[6 ])
+ m[4 ] * (m[1 ] * m[14] - m[13] * m[2 ])
- m[12] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]);
break;
// r=3, c=3
/* 00 04 08
01 05 09
02 06 10 */
case 15:
result = + m[0 ] * (m[5 ] * m[10] - m[9 ] * m[6 ])
- m[4 ] * (m[1 ] * m[10] - m[9 ] * m[2 ])
+ m[8 ] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]);
break;
default:
break;
}
float result = tab[0][0] * (tab[1][1] * tab[2][2] - tab[1][2] * tab[2][1])
- tab[0][1] * (tab[1][0] * tab[2][2] - tab[1][2] * tab[2][0])
+ tab[0][2] * (tab[1][0] * tab[2][1] - tab[1][1] * tab[2][0]);
if ((i + j) % 2 == 0)
result = -result;
return result;
}
@ -133,19 +297,16 @@ struct Matrix
inline void Invert()
{
float d = Det();
if (fabs(d) <= Math::TOLERANCE)
return;
assert(! IsZero(d));
Matrix temp = *this;
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 4; ++c)
{
m[r][c] = (1.0f / d) * temp.Cofactor(r, c);
m[4*r+c] = (1.0f / d) * temp.Cofactor(r, c);
}
}
Tranpose();
}
//! Multiplies the matrix with the given matrix
@ -153,14 +314,14 @@ struct Matrix
inline void Multiply(const Matrix &right)
{
Matrix left = *this;
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 4; ++c)
{
for (int c = 0; c < 4; ++c)
for (int r = 0; r < 4; ++r)
{
m[r][c] = 0.0;
m[4*c+r] = 0.0f;
for (int i = 0; i < 4; ++i)
{
m[4*r+c] += left.m[4*r+i] * right.m[4*i+c];
m[4*c+r] += left.m[4*i+r] * right.m[4*c+i];
}
}
}
@ -168,17 +329,16 @@ struct Matrix
//! Loads view matrix from the given vectors
/** \a from origin
\a at direction
\a up up vector */
inline void LoadView(const Vector &from, const Vector &at, const Vector &up)
\a at view direction
\a worldUp up vector */
inline void LoadView(const Vector &from, const Vector &at, const Vector &worldUp)
{
// Get the z basis vector, which points straight ahead. This is the
// difference from the eyepoint to the lookat point.
Vector view = at - from;
FLOAT length = view.Length();
if( IsZero(length) )
return;
float length = view.Length();
assert(! Math::IsZero(length) );
// Normalize the z basis vector
view /= length;
@ -200,8 +360,7 @@ struct Matrix
{
up = Vector(0.0f, 0.0f, 1.0f) - view.z * view;
if ( IsZero(up.Length()) )
return;
assert(! IsZero(up.Length()) );
}
}
@ -220,9 +379,9 @@ struct Matrix
m[8 ] = right.z; m[9 ] = up.z; m[10] = view.z;
// Do the translation values (rotations are still about the eyepoint)
m[3 ] = - DotProduct(from, right);
m[7 ] = - DotProduct(from, up);
m[11] = - DotProduct(from, view);
m[12] = - DotProduct(from, right);
m[13] = - DotProduct(from, up);
m[14] = - DotProduct(from, view);
}
inline void LoadProjection(float fov = 1.570795f, float aspect = 1.0f,
@ -233,12 +392,18 @@ struct Matrix
inline void LoadTranslation(const Vector &trans)
{
// TODO
LoadIdentity();
m[12] = trans.x;
m[13] = trans.y;
m[14] = trans.z;
}
inline void LoadScale(const Vector &scale)
{
// TODO
LoadIdentity();
m[0] = scale.x;
m[5] = scale.y;
m[10] = scale.z;
}
inline void LoadRotationX(float angle)
@ -264,22 +429,26 @@ struct Matrix
//! Calculates the matrix to make three rotations in the order X, Z and Y
inline void RotateXZY(const Vector &angle)
{
this->LoadRotationX(angle.x);
Matrix temp;
temp.SetRotateXMatrix(angle.x);
this->SetRotateZMatrix(angle.z);
temp.LoadRotationZ(angle.z);
this->Multiply(temp);
temp.SetRotateYMatrix(angle.y);
temp.LoadRotationY(angle.y);
this->Multiply(temp);
}
//! Calculates the matrix to make three rotations in the order Z, X and Y
inline void RotateZXY(const Vector &angle)
{
this->LoadRotationZ(angle.z);
Matrix temp;
temp.SetRotateZMatrix(angle.z);
this->SetRotateXMatrix(angle.x);
temp.LoadRotationX(angle.x);
this->Multiply(temp);
temp.SetRotateYMatrix(angle.y);
temp.LoadRotationY(angle.y);
this->Multiply(temp);
}
};
@ -287,7 +456,7 @@ struct Matrix
//! Convenience function for inverting a matrix
/** \a m input matrix
\a result result -- inverted matrix */
void InvertMatrix(const Matrix &m, Matrix &result)
inline void InvertMatrix(const Matrix &m, Matrix &result)
{
result = m;
result.Invert();
@ -296,11 +465,42 @@ void InvertMatrix(const Matrix &m, Matrix &result)
//! Convenience function for multiplying a matrix
/** \a left left-hand matrix
\a right right-hand matrix
\a result result -- multiplied matrices */*
void MultiplyMatrices(const Matrix &left, const Matrix &right, Matrix &result)
\a result result -- multiplied matrices */
inline void MultiplyMatrices(const Matrix &left, const Matrix &right, Matrix &result)
{
result = left;
result.Multiply(right);
}
//! Calculates the result of multiplying m * v
inline Vector MatrixVectorMultiply(const Matrix &m, const Vector &v)
{
float x = v.x * m.m[0 ] + v.y * m.m[4 ] + v.z * m.m[8 ] + m.m[12];
float y = v.x * m.m[1 ] + v.y * m.m[5 ] + v.z * m.m[9 ] + m.m[13];
float z = v.x * m.m[2 ] + v.y * m.m[6 ] + v.z * m.m[10] + m.m[14];
float w = v.x * m.m[4 ] + v.y * m.m[7 ] + v.z * m.m[11] + m.m[15];
if (IsZero(w))
return Vector(x, y, z);
x /= w;
y /= w;
z /= w;
return Vector(x, y, z);
}
//! Checks if two matrices are equal within given \a tolerance
inline bool MatricesEqual(const Math::Matrix &m1, const Math::Matrix &m2,
float tolerance = Math::TOLERANCE)
{
for (int i = 0; i < 16; ++i)
{
if (! IsEqual(m1.m[i], m2.m[i], tolerance))
return false;
}
return true;
}
}; // namespace Math

View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE debug)
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0")
add_executable(matrix_test matrix_test.cpp)
enable_testing()
add_test(matrix_test ./matrix_test)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS matrix_test)
add_custom_target(distclean COMMAND rm -rf ./matrix_test CMakeFiles Testing cmake_install.cmake CMakeCache.txt CTestTestfile.cmake Makefile)

86
src/math/test/gendata.m Normal file
View File

@ -0,0 +1,86 @@
% Script in Octave for generating test data
1;
% Returns the minor matrix
function m = minor(A, r, c)
m = A;
m(r,:) = [];
m(:,c) = [];
end;
% Returns the cofactor matrix
function m = cofactors(A)
m = zeros(rows(A), columns(A));
for r = [1 : rows(A)]
for c = [1 : columns(A)]
m(r, c) = det(minor(A, r, c));
if (mod(r + c, 2) == 1)
m(r, c) = -m(r, c);
end;
end;
end;
end;
% Prints the matrix as C++ code
function printout(A, name)
printf('const float %s[16] = \n', name);
printf('{\n');
for c = [1 : columns(A)]
for r = [1 : rows(A)]
printf(' %f', A(r,c));
if (! ( (r == 4) && (c == 4) ) )
printf(',');
end;
printf('\n');
end;
end;
printf('};\n');
end;
printf('// Cofactors\n');
A = randn(4,4);
printout(A, 'COF_MAT');
printf('\n');
printout(cofactors(A), 'COF_RESULT');
printf('\n');
printf('\n');
printf('// Det\n');
A = randn(4,4);
printout(A, 'DET_MAT');
printf('\n');
printf('const float DET_RESULT = %f;', det(A));
printf('\n');
printf('\n');
printf('// Invert\n');
A = randn(4,4);
printout(A, 'INV_MAT');
printf('\n');
printout(inv(A), 'COF_RESULT');
printf('\n');
printf('\n');
printf('// Multiplication\n');
A = randn(4,4);
printout(A, 'MUL_A');
printf('\n');
B = randn(4,4);
printout(B, 'MUL_B');
printf('\n');
C = A * B;
printout(C, 'MUL_RESULT');
printf('\n');

View File

@ -0,0 +1,287 @@
// * This file is part of the COLOBOT source code
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
// math/test/matrix_test.cpp
/* Unit tests for Matrix struct
Test data was randomly generated and the expected
results calculated using GNU Octave.
*/
#include "../func.h"
#include "../matrix.h"
#include <cstdio>
using namespace std;
const float TEST_TOLERANCE = 1e-5;
int TestCofactor()
{
const float TEST_MATRIX[16] =
{
-0.306479,
-0.520207,
0.127906,
0.632922,
-0.782876,
0.015264,
0.337479,
1.466013,
0.072725,
-0.315123,
1.613198,
-0.577377,
0.962397,
-1.320724,
1.467588,
0.579020
};
const float EXPECTED_RESULTS[4][4] =
{
{ 2.791599, -0.249952, 1.065075, -1.356570 },
{ 3.715943, -1.537511, 0.094812, -0.074520 },
{ 1.034500, -0.731752, -0.920756, -0.196235 },
{ 1.213928, -1.236857, 0.779741, -0.678482 }
};
Math::Matrix mat(TEST_MATRIX);
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 4; ++c)
{
float ret = mat.Cofactor(r, c);
float exp = EXPECTED_RESULTS[r][c];
if (! Math::IsEqual(ret, exp, TEST_TOLERANCE))
{
fprintf(stderr, "Cofactor r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp);
return 4*c+r;
}
}
}
return 0;
}
int TestDet()
{
const float TEST_MATRIX[16] =
{
0.85554,
0.11624,
1.30411,
0.81467,
0.49692,
-1.92483,
-1.33543,
0.85042,
-0.16775,
0.35344,
1.40673,
0.13961,
1.40709,
0.11731,
0.69042,
0.91216
};
const float EXPECTED_RESULT = 0.084360;
float ret = Math::Matrix(TEST_MATRIX).Det();
if (! Math::IsEqual(ret, EXPECTED_RESULT, TEST_TOLERANCE))
{
fprintf(stderr, "Det %f (returned) != %f (expected)\n", ret, EXPECTED_RESULT);
return 1;
}
return 0;
}
int TestInvert()
{
const float TEST_MATRIX[16] =
{
1.4675123,
-0.2857923,
-0.0496217,
-1.2825408,
-0.2804135,
-0.0826255,
-0.6825495,
1.1661259,
0.0032798,
0.5999200,
-1.8359883,
-1.1894424,
-1.1501538,
-2.8792485,
0.0299345,
0.3730919
};
const float EXPECTED_RESULT[16] =
{
0.685863,
0.562274,
-0.229722,
-0.132079,
-0.266333,
-0.139862,
0.054211,
-0.305568,
-0.130817,
-0.494076,
-0.358226,
-0.047477,
0.069486,
0.693649,
-0.261074,
-0.081200
};
Math::Matrix mat(TEST_MATRIX);
mat.Invert();
if (! Math::MatricesEqual(mat, EXPECTED_RESULT, TEST_TOLERANCE))
{
fprintf(stderr, "Invert mismatch\n");
return 1;
}
return 0;
}
int TestMultiply()
{
const float TEST_MATRIX_A[16] =
{
-1.931420,
0.843410,
0.476929,
-0.493435,
1.425659,
-0.176331,
0.129096,
0.551081,
-0.543530,
-0.190783,
-0.084744,
1.379547,
-0.473377,
1.643398,
0.400539,
0.702937
};
const float TEST_MATRIX_B[16] =
{
0.3517561,
1.3903778,
-0.8048254,
-0.4090024,
-1.5542159,
-0.6798636,
1.6003393,
-0.1467117,
0.5043620,
-0.0068779,
2.0697285,
-0.0463650,
0.9605451,
-0.4620149,
1.2525952,
-1.3409909
};
const float EXPECTED_RESULT[16] =
{
1.933875,
-0.467099,
0.251638,
-0.805156,
1.232207,
-1.737383,
-1.023401,
2.496859,
-2.086953,
-0.044468,
0.045688,
2.570036,
-2.559921,
-1.551155,
-0.244802,
0.056808
};
Math::Matrix matA(TEST_MATRIX_A);
Math::Matrix matB(TEST_MATRIX_B);
Math::Matrix mat;
Math::MultiplyMatrices(matA, matB, mat);
if (! Math::MatricesEqual(mat, Math::Matrix(EXPECTED_RESULT), TEST_TOLERANCE ) )
{
fprintf(stderr, "Multiply mismath!\n");
return 1;
}
return 0;
}
int main()
{
int result = 0;
result = TestCofactor();
if (result != 0)
return result;
result = TestDet();
if (result != 0)
return result;
result = TestInvert();
if (result != 0)
return result;
result = TestMultiply();
if (result != 0)
return result;
return result;
}

View File

@ -21,6 +21,7 @@
#pragma once
#include "const.h"
#include "func.h"
#include <cmath>
@ -85,16 +86,16 @@ struct Vector
this->z = z;
}
//! Loads the zero vector (0, 0, 0, 0)
//! Loads the zero vector (0, 0, 0)
inline void LoadZero()
{
x = y = z = w = 0.0f;
x = y = z = 0.0f;
}
//! Returns the vector length
inline float Length() const
{
return sqrt(x*x + y*y + z*z + w*w);
return sqrt(x*x + y*y + z*z);
}
//! Normalizes the vector
@ -104,12 +105,11 @@ struct Vector
x /= l;
y /= l;
z /= l;
w /= l;
}
//! Calculates the cross product with another vector
/** \a right right-hand side vector */
inline void Cross(const Vector &right)
inline void CrossMultiply(const Vector &right)
{
Vector left = *this;
x = left.y * right.z - left.z * right.y;
@ -118,7 +118,7 @@ struct Vector
}
//! Calculates the dot product with another vector
inline float Dot(const Vector &right) const
inline float DotMultiply(const Vector &right) const
{
return x * right.x + y * right.y + z * right.z;
}
@ -126,7 +126,7 @@ struct Vector
//! Returns the cosine of angle between this and another vector
inline float CosAngle(const Vector &right) const
{
return Dot(right) / (Length() * right.Length());
return DotMultiply(right) / (Length() * right.Length());
}
//! Returns angle (in radians) between this and another vector
@ -135,34 +135,90 @@ struct Vector
return acos(CosAngle(right));
}
//! Calculates the result of multiplying m * this vector
inline MatrixMultiply(const Matrix &m)
//! Returns the inverted vector
inline Vector operator-() const
{
float tx = x * m.m[0 ] + y * m.m[4 ] + z * m.m[8 ] + m.m[12];
float ty = x * m.m[1 ] + y * m.m[5 ] + z * m.m[9 ] + m.m[13];
float tz = x * m.m[2 ] + y * m.m[6 ] + z * m.m[10] + m.m[14];
float tw = x * m.m[4 ] + y * m.m[7 ] + z * m.m[11] + m.m[15];
return Vector(-x, -y, -z);
}
if (IsZero(tw))
return;
//! Adds the given vector
inline const Vector& operator+=(const Vector &right)
{
x += right.x;
y += right.y;
z += right.z;
return *this;
}
x = tx / tw;
y = ty / tw;
z = tz / tw;
//! Adds two vectors
inline friend const Vector operator+(const Vector &left, const Vector &right)
{
return Vector(left.x + right.x, left.y + right.y, left.z + right.z);
}
//! Subtracts the given vector
inline const Vector& operator-=(const Vector &right)
{
x -= right.x;
y -= right.y;
z -= right.z;
return *this;
}
//! Subtracts two vectors
inline friend const Vector operator-(const Vector &left, const Vector &right)
{
return Vector(left.x - right.x, left.y - right.y, left.z - right.z);
}
//! Multiplies by given scalar
inline const Vector& operator*=(const float &right)
{
x *= right;
y *= right;
z *= right;
return *this;
}
//! Multiplies vector by scalar
inline friend const Vector operator*(const float &left, const Vector &right)
{
return Vector(left * right.x, left * right.y, left * right.z);
}
//! Multiplies vector by scalar
inline friend const Vector operator*(const Vector &left, const float &right)
{
return Vector(left.x * right, left.y * right, left.z * right);
}
//! Divides by given scalar
inline const Vector& operator/=(const float &right)
{
x /= right;
y /= right;
z /= right;
return *this;
}
//! Divides vector by scalar
inline friend const Vector operator/(const Vector &left, const float &right)
{
return Vector(left.x / right, left.y / right, left.z / right);
}
};
//! Convenience function for calculating dot product
float DotProduct(const Vector &left, const Vector &right)
inline float DotProduct(const Vector &left, const Vector &right)
{
return left.DotProduct(right);
return left.DotMultiply(right);
}
//! Convenience function for calculating cross product
Vector CrossProduct(const Vector &left, const Vector &right)
inline Vector CrossProduct(const Vector &left, const Vector &right)
{
Vector result = left;
result.CrossProduct(right);
result.CrossMultiply(right);
return result;
}