// BlockyFroggy
// Copyright © 2017 John Ryland.
// All rights reserved.
#pragma once
#ifndef MATHS_H
#define MATHS_H
#include <cmath>
#include <random>
#define restrict __restrict
namespace Math
{
float dotProduct(const float *v1, const float *v2, int stride1 = 1, int stride2 = 1, int count = 4);
void crossProduct(float *restrict out, const float *restrict v1, const float *restrict v2);
void quatProduct(float *restrict out, const float *restrict v1, const float *restrict v2);
void transformVector(float *restrict vout, const float *restrict m, const float *restrict vin);
void normalizeVector(float *vInOut, int count = 4);
// Functions to make a new matrix
void makeIdentityMatrix4x4(float* out);
void makePerspectiveMatrix4x4(float* out, float a_fov, float a_aspect, float a_near, float a_far);
void makeOrthographicMatrix4x4(float* out, float , float , float, float, float a_near, float a_far);
void translationRotationScaleToMatrix4x4(float *restrict out, const float *restrict translate, const float *restrict rot, float uniformScale);
void translationQuatScaleToMatrix4x4(float *restrict out, const float *restrict translate, const float *restrict quat, float uniformScale);
// Conversion functions
void eulerToQuat(float *restrict out, float heading, float attitude, float bank);
void quatToMatrix4x4(float *restrict out, const float *restrict a_quat);
// Apply transfomations to a matrix (pass in an identity matrix if need to make a matrix)
void translateMatrix4x4(float *restrict inOut, const float *restrict vec3);
void scaleMatrix4x4(float *restrict inOut, const float *restrict vec3);
void rotateMatrix4x4(float *restrict inOut, const float *restrict vec3);
void quatRotateMatrix4x4(float *restrict inOut, const float *restrict a_quat); // quaternion
void translateMatrix4x4(float* inOut, float x, float y, float z);
void scaleMatrix4x4(float* inOut, float x, float y, float z);
void rotateMatrix4x4(float* inOut, float x, float y, float z);
// If apply rotation about an arbitary axis at a time (vec3 is the direction about which to rotate around)
void rotateAxisMatrix4x4(float *restrict inOut, float radians, const float *restrict vec3);
void rotateAxisMatrix4x4(float* inOut, float rad, float x, float y, float z);
// Helpers
void multiplyMatrix4x4(float *restrict out, const float *restrict m1, const float *restrict m2);
bool matrix4x4ToNormalMatrix3x3(float *restrict out, const float *restrict m);
bool inverseMatrix4x4(float *restrict out, const float *restrict m);
void transposeMatrix4x4(float *restrict out, const float *restrict m);
// Unit conversion helpers
float degreesToRadians(float degrees);
float radiansToDegrees(float radians);
// Golden ratio
float phi();
// Wikipedia:
//double phi() { return 1.6180339887498948482; }
// Others use it as 1.0 / 1.618034 = 0.618034
// Camera helpers
void makeCameraMatrix(float *restrict out, float fov, float aspect, const float restrict translate[3], const float restrict rotate[3], float scale, bool ortho);
void extractClipPlanes(float restrict clipPlanes[6][4], const float *restrict m);
bool isClipped(float clipPlanes[6][4], float x, float y, float z, float w, float h, float d);
void calcFrustum(float restrict frustumPts[8][4], const float *restrict m);
template <typename T>
inline T lerp(T t0, T t1, float ratio)
{
return t0 + ratio * (t1 - t0);
}
template <typename T>
inline T clamp(T t, T t1, T t2)
{
T max = t > t1 ? t : t1;
return max > t2 ? t2 : max;
}
/*
template <typename T>
inline T floor2(T t1, T t2) {
// 0.5 -> 0.0 -0.5 -> -1.0
return T(int(((t1 - ((t2+1)>>1))/t2)));
}
*/
// different result to x%y, result here should always be positive
template <typename T>
T modulus(T x, T y)
{
// return x - y * ((x-y+T(1))/y);
return x - y * int(floor(float(x)/y)); // inefficient at the moment, probably can do much better if test and use something like the floor2 function above
}
// different results to fmod, this function matches what glsl shaders mod function does
// this is important for predicting where a model will be rendered when allowing the vertex shader
// to wrap positions
template <typename T>
float modulus(float x, float y)
{
return x - y * floor(x/y);
}
class RandomNumberGenerator
{
public:
RandomNumberGenerator() : gen(rd()) {}
template <typename T>
T generate(T min = 0, T max = std::numeric_limits<T>::max())
{
std::uniform_int_distribution<T> dis(min, max);
return dis(gen);
}
private:
std::random_device rd;
std::mt19937 gen;
};
}
#endif // MATHS_H