/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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 . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of HPL1 Engine. */ #ifndef HPL_MATH_H #define HPL_MATH_H #include "hpl1/engine/math/BoundingVolume.h" #include "hpl1/engine/math/MathTypes.h" #include "hpl1/engine/math/MeshTypes.h" #include "hpl1/engine/graphics/Color.h" namespace hpl { class cMath { public: ////////////////////////////////////////////////////// ////////// RANDOM GENERATION //////////////////////// ////////////////////////////////////////////////////// /** * Generates a random integer from min to max * \param alMin * \param alMax * \return */ static int RandRectl(int alMin, int alMax); /** * Generates a random float from min to max * \param alMin * \param alMax * \return */ static float RandRectf(float alMin, float alMax); /** * Generates a random float from min to max */ static cVector2f RandRectVector2f(const cVector3f &avMin, const cVector3f &avMax); /** * Generates a random float from min to max */ static cVector3f RandRectVector3f(const cVector3f &avMin, const cVector3f &avMax); /** * Generates a random float from min to max */ static cColor RandRectColor(const cColor &aMin, const cColor &aMax); /** * Randomize the rand funcs. * \param alSeed the seed, -1 = random seed. */ static void Randomize(int alSeed = -1); ////////////////////////////////////////////////////// ////////// COLLSION ////////////////////////////////// ////////////////////////////////////////////////////// static bool BoxCollision(cRect2l aRect1, cRect2l aRect2); static bool BoxCollision(cRect2f aRect1, cRect2f aRect2); static bool PointBoxCollision(cVector2f avPoint, cRect2f aRect); static bool BoxFit(cRect2l aRectSrc, cRect2l aRectDest); static bool BoxFit(cRect2f aRectSrc, cRect2f aRectDest); static float Dist2D(const cVector2f &avPosA, const cVector2f &avPosB); static float Dist2D(const cVector3f &avPosA, const cVector3f &avPosB); static float SqrDist2D(const cVector2f &avPosA, const cVector2f &avPosB); static float SqrDist2D(const cVector3f &avPosA, const cVector3f &avPosB); static cRect2f &ClipRect(cRect2f &aRectSrc, const cRect2f &aRectDest); /** * Checks collison between two bounding volumes. * \return true if collision, else false. */ static bool CheckCollisionBV(cBoundingVolume &aBV1, cBoundingVolume &aBV2); static bool PointBVCollision(const cVector3f &avPoint, cBoundingVolume &aBV2); /** * Creates a clip rect for a bounding volume in screen space. * \return false if behind near clip. */ static bool GetClipRectFromBV(cRect2l &aDestRect, cBoundingVolume &aBV, const cMatrixf &a_mtxView, const cMatrixf &a_mtxProj, float afNearClipPlane, const cVector2l &avScreenSize); static bool CheckSphereInPlanes(const cVector3f &avCenter, float afRadius, const cPlanef *apPlanes, int alPlaneCount); ////////////////////////////////////////////////////// ////////// FLOAT OPERATIONS //////////////////////// ////////////////////////////////////////////////////// /** * Get fraction part of a float * \param afVal * \return */ static float GetFraction(float afVal); /** * Moldus (%) of a float * \param afDividend * \param afDivisor * \return */ static float Modulus(float afDividend, float afDivisor); static float ToRad(float afAngle); static float ToDeg(float afAngle); /** * Get the Log 2 of an int. */ static int Log2ToInt(int alX); /** * Checks if the number is a power of two. */ static bool IsPow2(int alX); /** * Wraps a value (afX) between min and max. Example: Wrap(-1, 0,10) returns 9. * \param afMin The minimum value. Must be lower than max. * \param afMax The maximum value. Must be higher than min and NOT 0. */ static float Wrap(float afX, float afMin, float afMax); /** * Clamps a value between min and max. Example Clamp(-1, 0,1) return 0. */ static float Clamp(float afX, float afMin, float afMax); inline static float Max(float afX, float afY) { if (afX > afY) return afX; return afY; } inline static float Min(float afX, float afY) { if (afX < afY) return afX; return afY; } inline static int Max(int alX, int alY) { if (alX > alY) return alX; return alY; } inline static int Min(int alX, int alY) { if (alX < alY) return alX; return alY; } inline static float Abs(float afX) { return afX < 0 ? -afX : afX; } inline static int Abs(int alX) { return alX < 0 ? -alX : alX; } static float GetAngleDistance(float afAngle1, float afAngle2, float afMaxAngle); static float GetAngleDistanceRad(float afAngle1, float afAngle2); static float GetAngleDistanceDeg(float afAngle1, float afAngle2); static float TurnAngle(float afAngle, float afFinalAngle, float afSpeed, float afMaxAngle); static float TurnAngleRad(float afAngle, float afFinalAngle, float afSpeed); static float TurnAngleDeg(float afAngle, float afFinalAngle, float afSpeed); static float InterpolateFloat(float afA, float afB, float afT); template static decltype(Vector::x) & GetVectorX(Vector &v) { return v.x; } template static decltype(Vector::y) & GetVectorY(Vector &v) { return v.y; } template static decltype(Vector::z) & GetVectorZ(Vector &v) { return v.z; } ////////////////////////////////////////////////////// ////////// VECTOR 2D /////////////////////////////// ////////////////////////////////////////////////////// /** * Get the angle a vector at aStartPos has to have to look at aGoalPos * \param &aStartPos * \param &avGoalPos * \return */ static float GetAngleFromPoints2D(const cVector2f &aStartPos, const cVector2f &avGoalPos); /** * Get a vector from an angle and a length * \param afAngle * \param afLength * \return */ static cVector2f GetVectorFromAngle2D(float afAngle, float afLength); /** * Get angle and length of a vector * \param &avVec * \param *apAngle * \param *apLength */ static void GetAngleFromVector(const cVector2f &avVec, float *apAngle, float *apLength); /** * Project Src on Dest * \param &avSrcVec * \param &avDestVec * \return */ static cVector2f ProjectVector2D(const cVector2f &avSrcVec, const cVector2f &avDestVec); ////////////////////////////////////////////////////// ////////// VECTOR 3D /////////////////////////////// ////////////////////////////////////////////////////// static inline cVector3f Vector3ToRad(const cVector3f &avVec) { return cVector3f(ToRad(avVec.x), ToRad(avVec.y), ToRad(avVec.z)); } static inline cVector3f Vector3ToDeg(const cVector3f &avVec) { return cVector3f(ToDeg(avVec.x), ToDeg(avVec.y), ToDeg(avVec.z)); } static inline cVector3f Vector3Normalize(const cVector3f &avVec) { cVector3f vNorm = avVec; vNorm.Normalise(); return vNorm; } static inline float Vector3DistSqr(const cVector3f &avStartPos, const cVector3f &avEndPos) { float fDX = avEndPos.x - avStartPos.x; float fDY = avEndPos.y - avStartPos.y; float fDZ = avEndPos.z - avStartPos.z; return fDX * fDX + fDY * fDY + fDZ * fDZ; } static inline float Vector3Dist(const cVector3f &avStartPos, const cVector3f &avEndPos) { return sqrt(Vector3DistSqr(avStartPos, avEndPos)); } static cVector3f GetAngleFromPoints3D(const cVector3f &avStartPos, const cVector3f &avGoalPos); /** * Vector cross product, A x B = R * \param avVecA * \param avVecB * \return */ static cVector3f Vector3Cross(const cVector3f &avVecA, const cVector3f &avVecB); /** * Vector dot product, A * B = R * \param avVecA * \param avVecB * \return */ static float Vector3Dot(const cVector3f &avVecA, const cVector3f &avVecB); /** * Project Src on Dest * \param &avSrcVec, must be normalized * \param &avDestVec, must be normalized * \return */ static cVector3f ProjectVector3D(const cVector3f &avSrcVec, const cVector3f &avDestVec); /** * Calculates the angle between two vectors. * \param avVecA * \param avVecB * \return */ static float Vector3Angle(const cVector3f &avVecA, const cVector3f &avVecB); /** * Unprojects a vector from screen size and coords. */ static cVector3f Vector3UnProject(const cVector3f &avVec, const cRect2f &aScreenRect, cMatrixf a_mtxViewProj); /** * Calculates distance from a point to a plane * \param aPlane The plane must be normalised! * \param avVec * \return >0 if in front of plane, 0 if on plane and <0 if behind plane */ static float PlaneToPointDist(const cPlanef &aPlane, const cVector3f &avVec); /** * Get the line defining the intersection of 2 planes. * \param aPA * \param aPB * \param avDir The direction of the line will be placed here * \param avPoint A point on the line will be placed here. */ static void PlaneIntersectionLine(const cPlanef &aPA, const cPlanef &aPB, cVector3f &avDir, cVector3f &avPoint); /** * Checks intersection with a frustum, an array of alPairNum plane pairs(alPairNum*2 planes), and a line, */ static bool CheckFrustumLineIntersection(const cPlanef *apPlanePairs, const cVector3f &avPoint1, const cVector3f &avPoint2, int alPairNum); /** * Checks intersection with a a frustum, an array of alPairNum plane pairs(alPairNum * 2 planes), and a quad mesh. * \param apPoints the points of the quad mesh, every 4 points is a face. */ static bool CheckFrustumQuadMeshIntersection(const cPlanef *apPlanePairs, tVector3fVec *apPoints, int alPairNum); ////////////////////////////////////////////////////// ////////// QUATERNIONS /////////////////////////////// ////////////////////////////////////////////////////// /** * Spherical Linear Interpolation between quaternions A and B * \param afT The amount in-between the quaternions. 0.0 is A and 1 is B. * \param abShortestPath Move the the shortest path. * \return */ static cQuaternion QuaternionSlerp(float afT, const cQuaternion &aqA, const cQuaternion &aqB, bool abShortestPath); static float QuaternionDot(const cQuaternion &aqA, const cQuaternion &aqB); ////////////////////////////////////////////////////// ////////// MATRIX //////////////////////////////////// ////////////////////////////////////////////////////// /** * Spherical Linear Interpolation between matrix A and B * \param afT The amount in-between the quaternions. 0.0 is A and 1 is B. * \param abShortestPath Move the the shortest path. * \return */ static cMatrixf MatrixSlerp(float afT, const cMatrixf &a_mtxA, const cMatrixf &a_mtxB, bool abShortestPath); /** * Matrix mulitplication, A * B = R. This means that B is applied BEFORE A. */ static cMatrixf MatrixMul(const cMatrixf &a_mtxA, const cMatrixf &a_mtxB); /** * Multiply and matrix and a 3d vector */ static cVector3f MatrixMul(const cMatrixf &a_mtxA, const cVector3f &avB); /** * Multiply and matrix and a 3d vector and divide the result with W. */ static cVector3f MatrixMulDivideW(const cMatrixf &a_mtxA, const cVector3f &avB); /** * Multiply matrix and a float. */ static cMatrixf MatrixMulScalar(const cMatrixf &a_mtxA, float afB); /** * Creates a rotation matrix along all axes according to order. */ static cMatrixf MatrixRotate(cVector3f avRot, eEulerRotationOrder aOrder); /** * Create a rotation matrix around the X-axis according to the right hand rule */ static cMatrixf MatrixRotateX(float afAngle); /** * Create a rotation matrix around the Y-axis according to the right hand rule */ static cMatrixf MatrixRotateY(float afAngle); /** * Create a rotation matrix around the Z-axis according to the right hand rule */ static cMatrixf MatrixRotateZ(float afAngle); static cMatrixf MatrixScale(cVector3f avScale); static cMatrixf MatrixTranslate(cVector3f avTrans); /** * Creates a matrix from a quaternion. * \return */ static cMatrixf MatrixQuaternion(const cQuaternion &aqRot); /** * Get the minor of a matrix. */ static inline float MatrixMinor(const cMatrixf &a_mtxA, const size_t r0, const size_t r1, const size_t r2, const size_t c0, const size_t c1, const size_t c2); /** * Get the adjoint of a matrix. */ static inline cMatrixf MatrixAdjoint(const cMatrixf &a_mtxA); /** * Get the determinant of a matrix. */ static inline float MatrixDeterminant(const cMatrixf &a_mtxA); /** * Gets the inverse of a matrix. */ static cMatrixf MatrixInverse(const cMatrixf &a_mtxA); /** * Converts the matrix into Euler angles, XYZ only supported at the moment. * \param &a_mtxA * \param aOrder */ static cVector3f MatrixToEulerAngles(const cMatrixf &a_mtxA, eEulerRotationOrder aOrder); /** * Create a char string from the matrix */ static const char *MatrixToChar(const cMatrixf &a_mtxA); ////////////////////////////////////////////////////// ////////// POLYGONS ////////////////////////////////// ////////////////////////////////////////////////////// /** * Creates an array with 4d tangent vectors for triangles. alIndexNum % 3 must be 0. * \param apDestArray The destination array, must be 4 * number of vertices large * \param apIndexArray The indices * \param alIndexNum Number of indices * \param apVertexArray Vertices indexed by the indices * \param apTexArray The texture coords * \param apNormalArray The normals * \param alVertexNum Number of vertex, normals and texcoords. * \return true if success, else false */ static bool CreateTriTangentVectors(float *apDestArray, const unsigned int *apIndexArray, int alIndexNum, const float *apVertexArray, int alVtxStride, const float *apTexArray, const float *apNormalArray, int alVertexNum); /** * Creates triangle data for a triangle mesh. alIndexNum % 3 must be 0. * \param avTriangles Where the data will be stored. If empty, this function resizes it. * \param apIndexArray The indices * \param alIndexNum Number of indices * \param apVertexArray Vertices indexed by the indices * \param alVertexNum Number of vertices * \return true if success, else false */ static bool CreateTriangleData(tTriangleDataVec &avTriangles, const unsigned int *apIndexArray, int alIndexNum, const float *apVertexArray, int alVtxStride, int alVertexNum); /** * Creates edges for a triangle mesh. alIndexNum % 3 must be 0. * \param avEdges An empty edge vector, this is where the edges will be stored. * \param apIndexArray The indices * \param alIndexNum Number of indices * \param apVertexArray Vertices indexed by the indices * \param alVertexNum Number of vertices * \return true if success, else false */ static bool CreateEdges(tTriEdgeVec &avEdges, const unsigned int *apIndexArray, int alIndexNum, const float *apVertexArray, int alVtxStride, int alVertexNum, bool *apIsDoubleSided); }; } // namespace hpl #endif // HPL_MATH_H