/* Copyright (c) 2019 Alex Diener This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alex Diener alex@ludobloom.com */ #ifndef __Scalar_H__ #define __Scalar_H__ #ifdef __cplusplus extern "C" { #endif #include static inline float clampf(float number, float min, float max) { if (number < min) { return min; } if (number > max) { return max; } return number; } static inline float clampi(int number, int min, int max) { if (number < min) { return min; } if (number > max) { return max; } return number; } static inline float clampu(unsigned int number, unsigned int min, unsigned int max) { if (number < min) { return min; } if (number > max) { return max; } return number; } static inline float interpolatef(float lhs, float rhs, float value) { return lhs + (rhs - lhs) * value; } static inline float roundpositivef(float number) { return floorf(number + 0.5f); } static inline double roundpositive(double number) { return floor(number + 0.5); } static inline float minf(float number1, float number2) { return number1 < number2 ? number1 : number2; } static inline float maxf(float number1, float number2) { return number1 > number2 ? number1 : number2; } // Accelerates ioVelocity linearly toward targetVelocity by the amount specified in timestep. // ioPosition is updated to an accurate value for any timestep size. // acceleration is the amount of change in velocity per second (or whatever time unit timestep represents). // The sign of acceleration is irrelevant, and it will be flipped if necessary to bring ioVelocity closer // to targetVelocity. void acceleratef(float * ioVelocity, float * ioPosition, float acceleration, float targetVelocity, float timestep); // ioX and ioY are treated as two coordinate values moving together in the direction specified by directionX // and directionY. For diagonal movement to look nice, every rounding threshold for x should be crossed at // the same time as it's crossed by y. This function copies the fractional part of one to the other in such // a way that at thresholds of a size specified by unitSize, both will be rounded to a new integer at the // same time. Preference is given to copy the fraction of whichever value would not decrease the value of // its counterpart in the specified direction. // The magnitude of directionX and directionY doesn't matter; they're only checked for sign and slope. void matchDiagonalFractionf(float * ioX, float * ioY, float directionX, float directionY, float unitSize); // Adjusts value to bring it closer to targetValue, returning the result. The adjustment is made in an // amount specified by speedPerSecond * timestep, in whichever direction would bring value closer to // targetValue. If adding or subtracting that amount would overshoot (or value is already equal to // targetValue), targetValue is returned. float rampTowardf(float value, float targetValue, float speedPerSecond, float timestep); #ifdef __cplusplus } #endif #endif