Added a quick printout of the hardware info. Running into a problem choosing between platforms, going to abstract CL out into it's own class and hide all that logic

This commit is contained in:
MitchellHansen
2016-08-14 00:03:44 -07:00
parent 3c9b39f682
commit edd8075afb
19 changed files with 2159 additions and 2084 deletions

View File

@@ -1,138 +1,138 @@
#pragma once
#include <SFML/Graphics.hpp>
#include <list>
class Curses {
public:
struct Slot {
Slot(wchar_t unicode_value_,
sf::Color font_color_,
sf::Color backfill_color_) :
unicode_value(unicode_value_),
font_color(font_color_),
backfill_color(backfill_color_)
{};
wchar_t unicode_value;
sf::Color font_color;
sf::Color backfill_color;
};
struct Tile {
public:
Tile(sf::Vector2i position_) :
blank_standby(L'\u0020', sf::Color::Transparent, sf::Color::Black),
position(position_)
{ };
private:
Slot blank_standby;
int index = 0; // What index in the vector are we. Backbone for blinking and scrolling
int ratio_counter = 0; // Secondary counter to hold index positions for (ratio) length of time
int ratio_value = 0;
std::vector<Slot> slot_stack; // The icon that aligns with the index
sf::Vector2i position; // Position of the text, and backfill
public:
void set_ratio(int ratio_) {
ratio_value = ratio_;
}
sf::Vector2i getPosition() const {
return position;
}
void push_back(Slot s) {
slot_stack.push_back(s);
}
void clear_and_set(Slot s) {
slot_stack.clear();
slot_stack.push_back(s);
}
void clear() {
slot_stack.clear();
}
sf::Color current_font_color() {
if (slot_stack.size() > 0)
return slot_stack.at(index).font_color;
else
return blank_standby.font_color;
}
sf::Color current_backfill_color() {
if (slot_stack.size() > 0)
return slot_stack.at(index).backfill_color;
else
return blank_standby.backfill_color;
}
wchar_t current_unicode_value() {
if (slot_stack.size() > 0)
return slot_stack.at(index).unicode_value;
else
return blank_standby.unicode_value;
}
void inc_index() {
if (index >= slot_stack.size() - 1) {
index = 0;
}
else if (ratio_counter == ratio_value) {
ratio_counter = 0;
index++;
}
else
ratio_counter++;
}
};
Curses(sf::Vector2i tile_size_, sf::Vector2i grid_dimensions);
~Curses();
void Update(double delta_time_);
void Render();
void setTile(Tile tile_);
void setTiles(std::vector<Tile> tiles_); // Can be seperate, non-adjacent tiles
void Clear();
Tile* getTile(sf::Vector2i position_);
std::vector<Curses::Tile*> getTiles(sf::Vector2i start_, sf::Vector2i end_);
void ResizeTiles(sf::Vector2i size_);
void ResizeTileGrid(sf::Vector2i grid_dimensions_);
void setBlink(int ratio_, sf::Vector2i position_);
void setScroll(int ratio_, sf::Vector2i start_, sf::Vector2i end_);
void setScroll(int ratio_, sf::Vector2i start_, std::list<Slot> tiles_);
private:
sf::Vector2i grid_dimensions;
sf::Vector2i tile_pixel_dimensions;
sf::RenderWindow window;
std::vector<Tile> tiles;
sf::Font font;
int multi_to_linear(sf::Vector2i position_) const;
sf::Vector2i linear_to_multi(int position_) const;
void set_tile_ratio(int ratio_, sf::Vector2i tile_position_);
void append_slots(sf::Vector2i start_, std::list<Slot> values_);
};
#pragma once
#include <SFML/Graphics.hpp>
#include <list>
class Curses {
public:
struct Slot {
Slot(wchar_t unicode_value_,
sf::Color font_color_,
sf::Color backfill_color_) :
unicode_value(unicode_value_),
font_color(font_color_),
backfill_color(backfill_color_)
{};
wchar_t unicode_value;
sf::Color font_color;
sf::Color backfill_color;
};
struct Tile {
public:
Tile(sf::Vector2i position_) :
blank_standby(L'\u0020', sf::Color::Transparent, sf::Color::Black),
position(position_)
{ };
private:
Slot blank_standby;
int index = 0; // What index in the vector are we. Backbone for blinking and scrolling
int ratio_counter = 0; // Secondary counter to hold index positions for (ratio) length of time
int ratio_value = 0;
std::vector<Slot> slot_stack; // The icon that aligns with the index
sf::Vector2i position; // Position of the text, and backfill
public:
void set_ratio(int ratio_) {
ratio_value = ratio_;
}
sf::Vector2i getPosition() const {
return position;
}
void push_back(Slot s) {
slot_stack.push_back(s);
}
void clear_and_set(Slot s) {
slot_stack.clear();
slot_stack.push_back(s);
}
void clear() {
slot_stack.clear();
}
sf::Color current_font_color() {
if (slot_stack.size() > 0)
return slot_stack.at(index).font_color;
else
return blank_standby.font_color;
}
sf::Color current_backfill_color() {
if (slot_stack.size() > 0)
return slot_stack.at(index).backfill_color;
else
return blank_standby.backfill_color;
}
wchar_t current_unicode_value() {
if (slot_stack.size() > 0)
return slot_stack.at(index).unicode_value;
else
return blank_standby.unicode_value;
}
void inc_index() {
if (index >= slot_stack.size() - 1) {
index = 0;
}
else if (ratio_counter == ratio_value) {
ratio_counter = 0;
index++;
}
else
ratio_counter++;
}
};
Curses(sf::Vector2i tile_size_, sf::Vector2i grid_dimensions);
~Curses();
void Update(double delta_time_);
void Render();
void setTile(Tile tile_);
void setTiles(std::vector<Tile> tiles_); // Can be seperate, non-adjacent tiles
void Clear();
Tile* getTile(sf::Vector2i position_);
std::vector<Curses::Tile*> getTiles(sf::Vector2i start_, sf::Vector2i end_);
void ResizeTiles(sf::Vector2i size_);
void ResizeTileGrid(sf::Vector2i grid_dimensions_);
void setBlink(int ratio_, sf::Vector2i position_);
void setScroll(int ratio_, sf::Vector2i start_, sf::Vector2i end_);
void setScroll(int ratio_, sf::Vector2i start_, std::list<Slot> tiles_);
private:
sf::Vector2i grid_dimensions;
sf::Vector2i tile_pixel_dimensions;
sf::RenderWindow window;
std::vector<Tile> tiles;
sf::Font font;
int multi_to_linear(sf::Vector2i position_) const;
sf::Vector2i linear_to_multi(int position_) const;
void set_tile_ratio(int ratio_, sf::Vector2i tile_position_);
void append_slots(sf::Vector2i start_, std::list<Slot> values_);
};

View File

@@ -1,46 +1,46 @@
#pragma once
#include <SFML/System/Vector3.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Color.hpp>
#include <random>
class Map {
public:
Map(sf::Vector3i dim) {
list = new char[dim.x * dim.y * dim.z];
for (int i = 0; i < dim.x * dim.y * dim.x; i++) {
list[i] = 0;
}
for (int x = 0; x < dim.x; x++) {
for (int y = 0; y < dim.y; y++) {
for (int z = 0; z < dim.z; z++) {
if (rand() % 100 < 1)
list[x + dim.x * (y + dim.z * z)] = rand() % 6;
else
list[x + dim.x * (y + dim.z * z)] = 0;
}
}
}
dimensions = dim;
global_light = sf::Vector3f(0.2, 0.4, 1);
}
~Map() {
}
sf::Vector3i getDimensions();
char *list;
sf::Vector3i dimensions;
void moveLight(sf::Vector2f in);
sf::Vector3f global_light;
protected:
private:
};
#pragma once
#include <SFML/System/Vector3.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Color.hpp>
#include <random>
class Map {
public:
Map(sf::Vector3i dim) {
list = new char[dim.x * dim.y * dim.z];
for (int i = 0; i < dim.x * dim.y * dim.x; i++) {
list[i] = 0;
}
for (int x = 0; x < dim.x; x++) {
for (int y = 0; y < dim.y; y++) {
for (int z = 0; z < dim.z; z++) {
if (rand() % 100 < 1)
list[x + dim.x * (y + dim.z * z)] = rand() % 6;
else
list[x + dim.x * (y + dim.z * z)] = 0;
}
}
}
dimensions = dim;
global_light = sf::Vector3f(0.2, 0.4, 1);
}
~Map() {
}
sf::Vector3i getDimensions();
char *list;
sf::Vector3i dimensions;
void moveLight(sf::Vector2f in);
sf::Vector3f global_light;
protected:
private:
};

View File

@@ -1,46 +1,46 @@
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include "Map.h"
class Ray {
private:
// The Tail of the vector
sf::Vector3<float> origin;
// Direction / Length of the vector
sf::Vector3<float> direction;
// The incrementing points at which T intersects int(X, Y, Z) points
sf::Vector3<float> intersection_t;
// The speed at which the ray climbs.
// Take the slope of the line (1 / cartesian.x/y/z) = delta_t.x/y/z
sf::Vector3<float> delta_t;
// The 3d voxel position the ray is currently at
sf::Vector3<int> voxel;
// The 2d pixel coordinate
sf::Vector2<int> pixel;
// Reference to the voxel map
Map *map;
// The dimensions of the voxel map
sf::Vector3<int> dimensions;
public:
Ray(
Map *m,
sf::Vector2<int> resolution,
sf::Vector2<int> pixel,
sf::Vector3<float> camera_position,
sf::Vector3<float> ray_direction
);
sf::Color Cast();
};
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include "Map.h"
class Ray {
private:
// The Tail of the vector
sf::Vector3<float> origin;
// Direction / Length of the vector
sf::Vector3<float> direction;
// The incrementing points at which T intersects int(X, Y, Z) points
sf::Vector3<float> intersection_t;
// The speed at which the ray climbs.
// Take the slope of the line (1 / cartesian.x/y/z) = delta_t.x/y/z
sf::Vector3<float> delta_t;
// The 3d voxel position the ray is currently at
sf::Vector3<int> voxel;
// The 2d pixel coordinate
sf::Vector2<int> pixel;
// Reference to the voxel map
Map *map;
// The dimensions of the voxel map
sf::Vector3<int> dimensions;
public:
Ray(
Map *m,
sf::Vector2<int> resolution,
sf::Vector2<int> pixel,
sf::Vector3<float> camera_position,
sf::Vector3<float> ray_direction
);
sf::Color Cast();
};

View File

@@ -1,46 +1,46 @@
#pragma once
#include <SFML/System/Vector3.hpp>
#include <SFML/System/Vector2.hpp>
#include <Map.h>
class RayCaster {
public:
RayCaster(Map *map,
sf::Vector3<int> map_dimensions,
sf::Vector2<int> viewport_resolution);
~RayCaster();
void setFOV(float fov);
void setResolution(sf::Vector2<int> resolution);
sf::Color* CastRays(sf::Vector3<float> camera_direction, sf::Vector3<float> camera_position);
void moveCamera(sf::Vector2f v);
private:
sf::Vector3<int> map_dimensions;
Map *map;
// The XY resolution of the viewport
sf::Vector2<int> resolution;
// The pixel array, maybe do RBGA? Are there even 4 byte data types?
sf::Color *image;
// The direction of the camera in POLAR coordinates
sf::Vector3<float> camera_direction;
// Convert the polar coordinates to CARTESIAN
sf::Vector3<float> camera_direction_cartesian;
// The world-space position of the camera
sf::Vector3<float> camera_position;
// The distance in units the view plane is from the iris point
int view_plane_distance = 200;
// Precalculated values for the view plane rays
sf::Vector3f *view_plane_vectors;
};
#pragma once
#include <SFML/System/Vector3.hpp>
#include <SFML/System/Vector2.hpp>
#include <Map.h>
class RayCaster {
public:
RayCaster(Map *map,
sf::Vector3<int> map_dimensions,
sf::Vector2<int> viewport_resolution);
~RayCaster();
void setFOV(float fov);
void setResolution(sf::Vector2<int> resolution);
sf::Color* CastRays(sf::Vector3<float> camera_direction, sf::Vector3<float> camera_position);
void moveCamera(sf::Vector2f v);
private:
sf::Vector3<int> map_dimensions;
Map *map;
// The XY resolution of the viewport
sf::Vector2<int> resolution;
// The pixel array, maybe do RBGA? Are there even 4 byte data types?
sf::Color *image;
// The direction of the camera in POLAR coordinates
sf::Vector3<float> camera_direction;
// Convert the polar coordinates to CARTESIAN
sf::Vector3<float> camera_direction_cartesian;
// The world-space position of the camera
sf::Vector3<float> camera_position;
// The distance in units the view plane is from the iris point
int view_plane_distance = 200;
// Precalculated values for the view plane rays
sf::Vector3f *view_plane_vectors;
};

View File

@@ -1,139 +1,139 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// 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.
//
////////////////////////////////////////////////////////////
#ifndef GAME_VECTOR3_H
#define GAME_VECTOR3_H
template <typename T>
class Vector3
{
public:
// Default constructor
// Creates a Vector3(0, 0, 0).
Vector3();
// Construct the vector from its coordinates
Vector3(T X, T Y, T Z);
// Construct the vector from another type of vector
// This constructor doesn't replace the copy constructor,
// it's called only when U != T.
// A call to this constructor will fail to compile if U
// is not convertible to T.
template <typename U>
explicit Vector3(const Vector3<U>& vector);
// Member data
T x;
T y;
T z;
};
// Vector3
// Overload of unary operator -
// left Vector to negate
// Memberwise opposite of the vector
template <typename T>
Vector3<T> operator -(const Vector3<T>& left);
// Overload of binary operator +=
// This operator performs a memberwise addition of both vectors,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator -=
// This operator performs a memberwise subtraction of both vectors,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator +
// returns Memberwise addition of both vectors
template <typename T>
Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator -
// returns Memberwise subtraction of both vectors
template <typename T>
Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator *
// returns Memberwise multiplication by right
template <typename T>
Vector3<T> operator *(const Vector3<T>& left, T right);
// Overload of binary operator *
// returns Memberwise multiplication by left
template <typename T>
Vector3<T> operator *(T left, const Vector3<T>& right);
// Overload of binary operator *=
// This operator performs a memberwise multiplication by right,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator *=(Vector3<T>& left, T right);
// Overload of binary operator /
// returns Memberwise division by right
template <typename T>
Vector3<T> operator /(const Vector3<T>& left, T right);
// Overload of binary operator /=
// This operator performs a memberwise division by right,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator /=(Vector3<T>& left, T right);
// Overload of binary operator ==
// This operator compares strict equality between two vectors.
// returns True if left is equal to right
template <typename T>
bool operator ==(const Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator !=
// This operator compares strict difference between two vectors.
// returns True if left is not equal to right
template <typename T>
bool operator !=(const Vector3<T>& left, const Vector3<T>& right);
#include <SFML/System/Vector3.inl>
// Define the most common types
typedef Vector3<int> Vector3i;
typedef Vector3<float> Vector3f;
#endif
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// 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.
//
////////////////////////////////////////////////////////////
#ifndef GAME_VECTOR3_H
#define GAME_VECTOR3_H
template <typename T>
class Vector3
{
public:
// Default constructor
// Creates a Vector3(0, 0, 0).
Vector3();
// Construct the vector from its coordinates
Vector3(T X, T Y, T Z);
// Construct the vector from another type of vector
// This constructor doesn't replace the copy constructor,
// it's called only when U != T.
// A call to this constructor will fail to compile if U
// is not convertible to T.
template <typename U>
explicit Vector3(const Vector3<U>& vector);
// Member data
T x;
T y;
T z;
};
// Vector3
// Overload of unary operator -
// left Vector to negate
// Memberwise opposite of the vector
template <typename T>
Vector3<T> operator -(const Vector3<T>& left);
// Overload of binary operator +=
// This operator performs a memberwise addition of both vectors,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator -=
// This operator performs a memberwise subtraction of both vectors,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator +
// returns Memberwise addition of both vectors
template <typename T>
Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator -
// returns Memberwise subtraction of both vectors
template <typename T>
Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator *
// returns Memberwise multiplication by right
template <typename T>
Vector3<T> operator *(const Vector3<T>& left, T right);
// Overload of binary operator *
// returns Memberwise multiplication by left
template <typename T>
Vector3<T> operator *(T left, const Vector3<T>& right);
// Overload of binary operator *=
// This operator performs a memberwise multiplication by right,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator *=(Vector3<T>& left, T right);
// Overload of binary operator /
// returns Memberwise division by right
template <typename T>
Vector3<T> operator /(const Vector3<T>& left, T right);
// Overload of binary operator /=
// This operator performs a memberwise division by right,
// and assigns the result to left.
// returns Reference to left
template <typename T>
Vector3<T>& operator /=(Vector3<T>& left, T right);
// Overload of binary operator ==
// This operator compares strict equality between two vectors.
// returns True if left is equal to right
template <typename T>
bool operator ==(const Vector3<T>& left, const Vector3<T>& right);
// Overload of binary operator !=
// This operator compares strict difference between two vectors.
// returns True if left is not equal to right
template <typename T>
bool operator !=(const Vector3<T>& left, const Vector3<T>& right);
#include <SFML/System/Vector3.inl>
// Define the most common types
typedef Vector3<int> Vector3i;
typedef Vector3<float> Vector3f;
#endif

View File

@@ -1,90 +1,90 @@
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include <math.h>
const double PI = 3.141592653589793238463;
const float PI_F = 3.14159265358979f;
struct fps_counter {
public:
fps_counter(){
if(!f.loadFromFile("../assets/fonts/Arial.ttf")){
std::cout << "couldn't find the fall back Arial font in ../assets/fonts/" << std::endl;
} else {
t.setFont(f);
}
}
void frame(double delta_time){
frame_count++;
fps_average += (delta_time - fps_average) / frame_count;
}
void draw(sf::RenderWindow *r){
t.setString(std::to_string(fps_average));
r->draw(t);
}
private:
sf::Font f;
sf::Text t;
int frame_count = 0;
double fps_average = 0;
};
inline sf::Vector3f SphereToCart(sf::Vector3f i) {
auto r = sf::Vector3f(
(i.x * sin(i.z) * cos(i.y)),
(i.x * sin(i.z) * sin(i.y)),
(i.x * cos(i.z))
);
return r;
};
inline sf::Vector3f CartToSphere(sf::Vector3f in) {
auto r = sf::Vector3f(
sqrt(in.x * in.x + in.y * in.y + in.z * in.z),
atan(in.y / in.x),
atan(sqrt(in.x * in.x + in.y * in.y) / in.z)
);
return r;
};
inline sf::Vector3f Normalize(sf::Vector3f in) {
float multiplier = sqrt(in.x * in.x + in.y * in.y + in.z * in.z);
auto r = sf::Vector3f(
in.x / multiplier,
in.y / multiplier,
in.z / multiplier
);
return r;
}
inline float DotProduct(sf::Vector3f a, sf::Vector3f b){
return a.x * b.x + a.y * b.y + a.z * b.z;
}
inline float Magnitude(sf::Vector3f in){
return sqrt(in.x * in.x + in.y * in.y + in.z * in.z);
}
inline float AngleBetweenVectors(sf::Vector3f a, sf::Vector3f b){
return acos(DotProduct(a, b) / (Magnitude(a) * Magnitude(b)));
}
inline float DegreesToRadians(float in) {
return in * PI / 180.0f;
}
inline float RadiansToDegrees(float in) {
return in * 180.0f / PI;
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include <math.h>
const double PI = 3.141592653589793238463;
const float PI_F = 3.14159265358979f;
struct fps_counter {
public:
fps_counter(){
if(!f.loadFromFile("../assets/fonts/Arial.ttf")){
std::cout << "couldn't find the fall back Arial font in ../assets/fonts/" << std::endl;
} else {
t.setFont(f);
}
}
void frame(double delta_time){
frame_count++;
fps_average += (delta_time - fps_average) / frame_count;
}
void draw(sf::RenderWindow *r){
t.setString(std::to_string(fps_average));
r->draw(t);
}
private:
sf::Font f;
sf::Text t;
int frame_count = 0;
double fps_average = 0;
};
inline sf::Vector3f SphereToCart(sf::Vector3f i) {
auto r = sf::Vector3f(
(i.x * sin(i.z) * cos(i.y)),
(i.x * sin(i.z) * sin(i.y)),
(i.x * cos(i.z))
);
return r;
};
inline sf::Vector3f CartToSphere(sf::Vector3f in) {
auto r = sf::Vector3f(
sqrt(in.x * in.x + in.y * in.y + in.z * in.z),
atan(in.y / in.x),
atan(sqrt(in.x * in.x + in.y * in.y) / in.z)
);
return r;
};
inline sf::Vector3f Normalize(sf::Vector3f in) {
float multiplier = sqrt(in.x * in.x + in.y * in.y + in.z * in.z);
auto r = sf::Vector3f(
in.x / multiplier,
in.y / multiplier,
in.z / multiplier
);
return r;
}
inline float DotProduct(sf::Vector3f a, sf::Vector3f b){
return a.x * b.x + a.y * b.y + a.z * b.z;
}
inline float Magnitude(sf::Vector3f in){
return sqrt(in.x * in.x + in.y * in.y + in.z * in.z);
}
inline float AngleBetweenVectors(sf::Vector3f a, sf::Vector3f b){
return acos(DotProduct(a, b) / (Magnitude(a) * Magnitude(b)));
}
inline float DegreesToRadians(float in) {
return in * PI / 180.0f;
}
inline float RadiansToDegrees(float in) {
return in * 180.0f / PI;
}