/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #pragma once // include required headers #include "StandardHeaders.h" #include "FastMath.h" namespace AZ { class Matrix4x4; class Vector2; class Vector3; } namespace MCore { /** * Project a 3D point in world space to 2D screen coordinates. * @param point The point in world space we want to map to the screen. * @param viewProjMatrix A precalculated version of viewMatrix * projectionMatrix used by the camera. * @param screenWidth The width of the screen in pixels. * @param screenHeight The height of the screen in pixels. * @return A three component vector containing the resulting 2D screen coordinates as well as the distance of the point to the camera. * x component: The horizontal screen coordinate. Zero means the coordinate is on the left border while a negative value means the * point even further to the left and not visible by the camera at all, a bigger value than screenWidth goes analogue for the right border. * y component: The vertical screen coordinate. Zero means the coordinate is on the top border while a negative value means the * point even further to the top and not visible by the camera at all, a bigger value than screenHeight goes analogue for the bottom border. * z component: The distance of the point to the camera. A negative value means the point is behind the camera and not visible. */ AZ::Vector3 MCORE_API Project(const AZ::Vector3& point, const AZ::Matrix4x4& viewProjMatrix, uint32 screenWidth, uint32 screenHeight); /** * Unproject screen coordinates to a 3D point in world space. * @param screenX The mouse position x value or another horizontal screen coordinate in range [0, screenWidth]. * @param screenY The mouse position y value or another vertical screen coordinate in range [0, screenHeight]. * @param screenWidth The width of the screen in pixels. * @param screenHeight The height of the screen in pixels. * @param depth . * @param viewMatrix The view matrix of the camera. * @param projectionMatrix The projection matrix of the camera. * @return The unprojected point in world space. */ AZ::Vector3 MCORE_API UnprojectToEyeSpace(float screenX, float screenY, const AZ::Matrix4x4& invProjMat, float windowWidth, float windowHeight, float depth); AZ::Vector3 MCORE_API Unproject(float screenX, float screenY, float screenWidth, float screenHeight, float depth, const AZ::Matrix4x4& invProjMat, const AZ::Matrix4x4& invViewMat); AZ::Vector3 MCORE_API UnprojectOrtho(float screenX, float screenY, float screenWidth, float screenHeight, float depth, const AZ::Matrix4x4& projectionMatrix, const AZ::Matrix4x4& viewMatrix); // AZ::Vector2 MCORE_API OrthogonalProject(const AZ::Vector3& pos); AZ::Vector3 MCORE_API OrthogonalUnproject(const AZ::Vector2& uv); AZ::Vector2 MCORE_API StereographicProject(const AZ::Vector3& pos); AZ::Vector3 MCORE_API StereographicUnproject(const AZ::Vector2& uv); // bool MCORE_API PointInPoly(AZ::Vector2* verts, uint32 numVerts, const AZ::Vector2& point); float MCORE_API DistanceToEdge(const AZ::Vector2& edgePointA, const AZ::Vector2& edgePointB, const AZ::Vector2& testPoint); AZ::Vector2 MCORE_API ClosestPointToPoly(const AZ::Vector2* polyPoints, uint32 numPoints, const AZ::Vector2& testPoint); /** * Calculates the CRC value of a given byte. * It inputs and modifies the current CRC value passed as parameter. * @param byteValue The byte value to generate the CRC for. * @param CRC The CRC value to modify. * * The calculation performed is: * <pre> * CRC = ((CRC) >> 8) ^ MCore::CRC32Table[(byteValue) ^ ((CRC) & 0x000000FF)]; * </pre> */ //void MCORE_API CalcCRC32(uint8 byteValue, uint32& CRC); /** * Calculate the cube root, which basically is pow(x, 1/3). * This also allows negative and zero values. * @param x The number. * @result The cube root. */ MCORE_INLINE float CubeRoot(float x); /** * Sample an ease-in/out curve. * The curve is split into three sections: an ease in part, a linear constant velocity mid section, and an ease out part. * The ease in and out parts are parts of a sine wave. * @param t The normalized time value, between 0 and 1. * @param k1 The normalized time value where the ease-in section stops. * @param k2 The normalized time value where the ease-out section starts. * @result The interpolation fraction value. Use "startValue + SampleEaseInOutCurve(...) * (endValue-startValue)" to interpolate, or use EaseInOutInterpolate(...). * @see EaseInOutInterpolate. */ MCORE_INLINE float SampleEaseInOutCurve(float t, float k1 = 0.5f, float k2 = 0.5f); /** * Sample an ease-in/out curve, while controlling the smoothness/linearity of both ease in and out parts. * You can use the smoothness values to control if this is an ease-in curve only, or ease-out or both ease-in/out, etc. * @param t The normalized time value, between 0 and 1. * @param easeInSmoothness The smoothness of the ease in part, where 0 means linear and 1 means smoothed. Values between 0 and 1 are valid. * @param easeOutSmoothness The smoothness of the ease out part, where 0 means linear and 1 means smoothed. Values between 0 and 1 are valid. * @result The interpolation fraction value. Use "startValue + SampleEaseInOutCurveWithSmoothness(...) * (endValue-startValue)" to interpolate, or use EaseInOutWithSmoothnessInterpolate(...). * @see EaseInOutWithSmoothnessInterpolate. */ MCORE_INLINE float SampleEaseInOutCurveWithSmoothness(float t, float easeInSmoothness = 1.0f, float easeOutSmoothness = 1.0f); /** * Convert a linear interpolation weight value that is between 0 and 1 into a * smoothed version of that value that is also between 0 and 1. * This can be used to easily convert a linear interpolation into smooth looking interpolation. * @param linearValue The linear weight value that is between 0 and 1. * @result The smoothed version of the linear value, also in range of 0..1. */ MCORE_INLINE float CalcCosineInterpolationWeight(float linearValue); /** * Linear interpolate from source into target. * @param source The source value to start interpolating from. * @param target The target value. * @param timeValue A value between 0 and 1, where 0 results in the source and 1 results in the target value. * @result The interpolated value. */ template <class T> MCORE_INLINE T LinearInterpolate(const T& source, const T& target, float timeValue); /** * Cosine interpolate from source into target. * @param source The source value to start interpolating from. * @param target The target value. * @param timeValue A value between 0 and 1, where 0 results in the source and 1 results in the target value. * @result The interpolated value. */ template <class T> MCORE_INLINE T CosineInterpolate(const T& source, const T& target, float timeValue); /** * Ease in/out interpolation. * @param source The source value to start interpolating from. * @param target The target value. * @param timeValue The normalized time value, between 0 and 1. * @param k1 The normalized time value where the ease-in section stops. * @param k2 The normalized time value where the ease-out section starts. * @result The interpolated value. */ template <class T> MCORE_INLINE T EaseInOutInterpolate(const T& source, const T& target, float timeValue, float k1 = 0.5f, float k2 = 0.5f); /** * Ease in/out interpolation, with smoothness control on both ease in and out parts. * @param source The source value to start interpolating from. * @param target The target value. * @param timeValue The normalized time value, between 0 and 1. * @param easeInSmoothness The smoothness of the ease in part, where 0 means linear and 1 means smoothed. Values between 0 and 1 are valid. * @param easeOutSmoothness The smoothness of the ease out part, where 0 means linear and 1 means smoothed. Values between 0 and 1 are valid. * @result The interpolated value. */ template <class T> MCORE_INLINE T EaseInOutWithSmoothnessInterpolate(const T& source, const T& target, float timeValue, float easeInSmoothness = 1.0f, float easeOutSmoothness = 1.0f); /** * Calculate an interpolated value using barycentric coordinates. * Given three attributes and an u and v, which range from 0..1, we can calculate the interpolated attribute value at the given u, v position. * @param u The barycentric u coordinate, between 0 and 1. * @param v The barycentric v coordinate, between 0 and 1. * @param pointA The first attribute value (for example the first vertex normal of a triangle). * @param pointB The second attribute value (for example the second vertex normal of a triangle). * @param pointC The third attribute value (for example the third vertex normal of the triangle). * @result The interpolated attribute value, at the given u and v coordinate. */ template <class T> MCORE_INLINE T BarycentricInterpolate(float u, float v, const T& pointA, const T& pointB, const T& pointC); /** * Swaps the two objects. * @param a The first object. * @param b The second object. */ template<class T> MCORE_INLINE void Swap(T& a, T& b); /** * Returns the smaller value of two objects. * @param a The first object. * @param b The second object. * @result The smaller value of the two. */ template<class T> MCORE_INLINE T Min(T a, T b); /** * Returns the greater value of two objects. * @param a The first object. * @param b The second object. * @result The greater value of the two. */ template<class T> MCORE_INLINE T Max(T a, T b); /** * Returns the smaller value of three objects. * @param a The first object. * @param b The second object. * @param c The third object. * @result The smaller value of the three. */ template<class T> MCORE_INLINE T Min3(T a, T b, T c); /** * Returns the greater value of three objects. * @param a The first object. * @param b The second object. * @param c The third object. * @result The greater value of the three. */ template<class T> MCORE_INLINE T Max3(T a, T b, T c); template<class T> MCORE_INLINE T Sgn(T A); /** * Calculates the square of the value. * @param x The value to square. * @return The square. */ template<class T> MCORE_INLINE T Square(T x); /** * Calculates the square of the value. * @param x The value to square. * @return The square. */ template<class T> MCORE_INLINE T Sqr(T x); /** * Returns true if the value is negative, false if not. * @param x The value to check. * @result True if the value is negative, false if not. */ template<class T> MCORE_INLINE bool IsNegative(T x); /** * Returns true if the value is negative, false if not. * @param x The value to check. * @result True if the value is negative, false if not. */ template<class T> MCORE_INLINE bool IsPositive(T x); /** * Modifies x if the object is lower than min or greater * than max and returns the object. * @param x The object to check. * @param min The minimal value. * @param max The maximal value. * @return The modified object. */ template<class T> MCORE_INLINE T Clamp(T x, T min, T max); /** * Returns true if the value is bigger or equal than the lower limit or smaller or equal than the high limit. * @param x The value to check. * @param low The low range limit. * @param high The high range limit. * @result Returns true if the value is bigger or equal than the lower limit or smaller or equal than the high limit, otherwise false. */ template<class T> MCORE_INLINE bool InRange(T x, T low, T high); /** * Convert from cartesian coordinates into spherical coordinates. * This uses the y-axis (up) and x-axis (right) as basis. * The input vector needs to be normalized! * @param normalizedVector The normalized direction vector to convert into spherical coordinates. * @result The spherical angles, in radians. */ AZ::Vector2 MCORE_API ToSpherical(const AZ::Vector3& normalizedVector); /** * Convert from spherical coordinates back into cartesian coordinates. * this uses the y-axis (up) and x-axis (right) as basis. * @param spherical The spherical coordinates, as returned by ToSpherical(...). * @result The unit direction vector that was converted from the spherical coordinates. */ AZ::Vector3 MCORE_API FromSpherical(const AZ::Vector2& spherical); /** * Calculate the number of samples and spacing between each samples, given a duration and number of samples per second. * This will make sure all samples are evenly spaced. * @param samplesPerSecond The desired number of samples per second. It is not guaranteed it will be exactly this amount though, because of alignment needed to * create evenly spaced samples. * @param duration The duration of the range in seconds. * @param outSampleTimeStep The spacing in seconds between the samples will be stored in this float. * @param outNumSamples The resulting number of samples needed to cover the range. */ void MCORE_API CalcSampleRateInfo(float samplesPerSecond, float duration, float* outSampleTimeStep, uint32* outNumSamples); /** * Calculate the area of the triangle based on three points in space. * @param v1 First point of the triangle. * @param v2 Second point of the triangle. * @param v3 Third point of the triangle. * @result The area of the triangle. */ double MCORE_API CalcTriangleAreaAccurate(const AZ::Vector3& v1, const AZ::Vector3& v2, const AZ::Vector3& v3); float MCORE_API CalcTriangleArea(const AZ::Vector3& v1, const AZ::Vector3& v2, const AZ::Vector3& v3); // include inline code #include "Algorithms.inl" } // namespace MCore