Batman
This commit is contained in:
102
project/src/BRDFs.h
Normal file
102
project/src/BRDFs.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
#include "Maths.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
namespace BRDF
|
||||
{
|
||||
/**
|
||||
* \param kd Diffuse Reflection Coefficient
|
||||
* \param cd Diffuse Color
|
||||
* \return Lambert Diffuse Color
|
||||
*/
|
||||
static ColorRGB Lambert(float kd, const ColorRGB& cd)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
static ColorRGB Lambert(const ColorRGB& kd, const ColorRGB& cd)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief todo
|
||||
* \param ks Specular Reflection Coefficient
|
||||
* \param exp Phong Exponent
|
||||
* \param l Incoming (incident) Light Direction
|
||||
* \param v View Direction
|
||||
* \param n Normal of the Surface
|
||||
* \return Phong Specular Color
|
||||
*/
|
||||
static ColorRGB Phong(float ks, float exp, const Vector3& l, const Vector3& v, const Vector3& n)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BRDF Fresnel Function >> Schlick
|
||||
* \param h Normalized Halfvector between View and Light directions
|
||||
* \param v Normalized View direction
|
||||
* \param f0 Base reflectivity of a surface based on IOR (Indices Of Refrection), this is different for Dielectrics (Non-Metal) and Conductors (Metal)
|
||||
* \return
|
||||
*/
|
||||
static ColorRGB FresnelFunction_Schlick(const Vector3& h, const Vector3& v, const ColorRGB& f0)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BRDF NormalDistribution >> Trowbridge-Reitz GGX (UE4 implemetation - squared(roughness))
|
||||
* \param n Surface normal
|
||||
* \param h Normalized half vector
|
||||
* \param roughness Roughness of the material
|
||||
* \return BRDF Normal Distribution Term using Trowbridge-Reitz GGX
|
||||
*/
|
||||
static float NormalDistribution_GGX(const Vector3& n, const Vector3& h, float roughness)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief BRDF Geometry Function >> Schlick GGX (Direct Lighting + UE4 implementation - squared(roughness))
|
||||
* \param n Normal of the surface
|
||||
* \param v Normalized view direction
|
||||
* \param roughness Roughness of the material
|
||||
* \return BRDF Geometry Term using SchlickGGX
|
||||
*/
|
||||
static float GeometryFunction_SchlickGGX(const Vector3& n, const Vector3& v, float roughness)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BRDF Geometry Function >> Smith (Direct Lighting)
|
||||
* \param n Normal of the surface
|
||||
* \param v Normalized view direction
|
||||
* \param l Normalized light direction
|
||||
* \param roughness Roughness of the material
|
||||
* \return BRDF Geometry Term using Smith (> SchlickGGX(n,v,roughness) * SchlickGGX(n,l,roughness))
|
||||
*/
|
||||
static float GeometryFunction_Smith(const Vector3& n, const Vector3& v, const Vector3& l, float roughness)
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
57
project/src/Camera.h
Normal file
57
project/src/Camera.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include <SDL_keyboard.h>
|
||||
#include <SDL_mouse.h>
|
||||
|
||||
#include "Maths.h"
|
||||
#include "Timer.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct Camera
|
||||
{
|
||||
Camera() = default;
|
||||
|
||||
Camera(const Vector3& _origin, float _fovAngle) :
|
||||
origin{ _origin },
|
||||
fovAngle{ _fovAngle }
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Vector3 origin{};
|
||||
float fovAngle{ 90.f };
|
||||
|
||||
Vector3 forward{ Vector3::UnitZ };
|
||||
Vector3 up{ Vector3::UnitY };
|
||||
Vector3 right{ Vector3::UnitX };
|
||||
|
||||
float totalPitch{ 0.f };
|
||||
float totalYaw{ 0.f };
|
||||
|
||||
Matrix cameraToWorld{};
|
||||
|
||||
|
||||
Matrix CalculateCameraToWorld()
|
||||
{
|
||||
//todo: W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
void Update(Timer* pTimer)
|
||||
{
|
||||
const float deltaTime = pTimer->GetElapsed();
|
||||
|
||||
//Keyboard Input
|
||||
const uint8_t* pKeyboardState = SDL_GetKeyboardState(nullptr);
|
||||
|
||||
|
||||
//Mouse Input
|
||||
int mouseX{}, mouseY{};
|
||||
const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY);
|
||||
|
||||
//todo: W2
|
||||
//throw std::runtime_error("Not Implemented Yet");
|
||||
}
|
||||
};
|
||||
}
|
||||
149
project/src/ColorRGB.h
Normal file
149
project/src/ColorRGB.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
#include "MathHelpers.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct ColorRGB
|
||||
{
|
||||
float r{};
|
||||
float g{};
|
||||
float b{};
|
||||
|
||||
void MaxToOne()
|
||||
{
|
||||
const float maxValue = std::max(r, std::max(g, b));
|
||||
if (maxValue > 1.f)
|
||||
*this /= maxValue;
|
||||
}
|
||||
|
||||
static ColorRGB Lerp(const ColorRGB& c1, const ColorRGB& c2, float factor)
|
||||
{
|
||||
return { Lerpf(c1.r, c2.r, factor), Lerpf(c1.g, c2.g, factor), Lerpf(c1.b, c2.b, factor) };
|
||||
}
|
||||
|
||||
#pragma region ColorRGB (Member) Operators
|
||||
const ColorRGB& operator+=(const ColorRGB& c)
|
||||
{
|
||||
r += c.r;
|
||||
g += c.g;
|
||||
b += c.b;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ColorRGB& operator+(const ColorRGB& c)
|
||||
{
|
||||
return *this += c;
|
||||
}
|
||||
|
||||
ColorRGB operator+(const ColorRGB& c) const
|
||||
{
|
||||
return { r + c.r, g + c.g, b + c.b };
|
||||
}
|
||||
|
||||
const ColorRGB& operator-=(const ColorRGB& c)
|
||||
{
|
||||
r -= c.r;
|
||||
g -= c.g;
|
||||
b -= c.b;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ColorRGB& operator-(const ColorRGB& c)
|
||||
{
|
||||
return *this -= c;
|
||||
}
|
||||
|
||||
ColorRGB operator-(const ColorRGB& c) const
|
||||
{
|
||||
return { r - c.r, g - c.g, b - c.b };
|
||||
}
|
||||
|
||||
const ColorRGB& operator*=(const ColorRGB& c)
|
||||
{
|
||||
r *= c.r;
|
||||
g *= c.g;
|
||||
b *= c.b;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ColorRGB& operator*(const ColorRGB& c)
|
||||
{
|
||||
return *this *= c;
|
||||
}
|
||||
|
||||
ColorRGB operator*(const ColorRGB& c) const
|
||||
{
|
||||
return { r * c.r, g * c.g, b * c.b };
|
||||
}
|
||||
|
||||
const ColorRGB& operator/=(const ColorRGB& c)
|
||||
{
|
||||
r /= c.r;
|
||||
g /= c.g;
|
||||
b /= c.b;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ColorRGB& operator/(const ColorRGB& c)
|
||||
{
|
||||
return *this /= c;
|
||||
}
|
||||
|
||||
const ColorRGB& operator*=(float s)
|
||||
{
|
||||
r *= s;
|
||||
g *= s;
|
||||
b *= s;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ColorRGB& operator*(float s)
|
||||
{
|
||||
return *this *= s;
|
||||
}
|
||||
|
||||
ColorRGB operator*(float s) const
|
||||
{
|
||||
return { r * s, g * s,b * s };
|
||||
}
|
||||
|
||||
const ColorRGB& operator/=(float s)
|
||||
{
|
||||
r /= s;
|
||||
g /= s;
|
||||
b /= s;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ColorRGB& operator/(float s)
|
||||
{
|
||||
return *this /= s;
|
||||
}
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
//ColorRGB (Global) Operators
|
||||
inline ColorRGB operator*(float s, const ColorRGB& c)
|
||||
{
|
||||
return c * s;
|
||||
}
|
||||
|
||||
namespace colors
|
||||
{
|
||||
static ColorRGB Red{ 1,0,0 };
|
||||
static ColorRGB Blue{ 0,0,1 };
|
||||
static ColorRGB Green{ 0,1,0 };
|
||||
static ColorRGB Yellow{ 1,1,0 };
|
||||
static ColorRGB Cyan{ 0,1,1 };
|
||||
static ColorRGB Magenta{ 1,0,1 };
|
||||
static ColorRGB White{ 1,1,1 };
|
||||
static ColorRGB Black{ 0,0,0 };
|
||||
static ColorRGB Gray{ 0.5f,0.5f,0.5f };
|
||||
}
|
||||
}
|
||||
181
project/src/DataTypes.h
Normal file
181
project/src/DataTypes.h
Normal file
@@ -0,0 +1,181 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "Maths.h"
|
||||
|
||||
|
||||
namespace dae
|
||||
{
|
||||
#pragma region GEOMETRY
|
||||
struct Sphere
|
||||
{
|
||||
Vector3 origin{};
|
||||
float radius{};
|
||||
|
||||
unsigned char materialIndex{ 0 };
|
||||
};
|
||||
|
||||
struct Plane
|
||||
{
|
||||
Vector3 origin{};
|
||||
Vector3 normal{};
|
||||
|
||||
unsigned char materialIndex{ 0 };
|
||||
};
|
||||
|
||||
enum class TriangleCullMode
|
||||
{
|
||||
FrontFaceCulling,
|
||||
BackFaceCulling,
|
||||
NoCulling
|
||||
};
|
||||
|
||||
struct Triangle
|
||||
{
|
||||
Triangle() = default;
|
||||
Triangle(const Vector3& _v0, const Vector3& _v1, const Vector3& _v2, const Vector3& _normal) :
|
||||
v0{ _v0 }, v1{ _v1 }, v2{ _v2 }, normal{ _normal.Normalized() } {}
|
||||
|
||||
Triangle(const Vector3& _v0, const Vector3& _v1, const Vector3& _v2) :
|
||||
v0{ _v0 }, v1{ _v1 }, v2{ _v2 }
|
||||
{
|
||||
const Vector3 edgeV0V1 = v1 - v0;
|
||||
const Vector3 edgeV0V2 = v2 - v0;
|
||||
normal = Vector3::Cross(edgeV0V1, edgeV0V2).Normalized();
|
||||
}
|
||||
|
||||
Vector3 v0{};
|
||||
Vector3 v1{};
|
||||
Vector3 v2{};
|
||||
|
||||
Vector3 normal{};
|
||||
|
||||
TriangleCullMode cullMode{};
|
||||
unsigned char materialIndex{};
|
||||
};
|
||||
|
||||
struct TriangleMesh
|
||||
{
|
||||
TriangleMesh() = default;
|
||||
TriangleMesh(const std::vector<Vector3>& _positions, const std::vector<int>& _indices, TriangleCullMode _cullMode) :
|
||||
positions(_positions), indices(_indices), cullMode(_cullMode)
|
||||
{
|
||||
//Calculate Normals
|
||||
CalculateNormals();
|
||||
|
||||
//Update Transforms
|
||||
UpdateTransforms();
|
||||
}
|
||||
|
||||
TriangleMesh(const std::vector<Vector3>& _positions, const std::vector<int>& _indices, const std::vector<Vector3>& _normals, TriangleCullMode _cullMode) :
|
||||
positions(_positions), indices(_indices), normals(_normals), cullMode(_cullMode)
|
||||
{
|
||||
UpdateTransforms();
|
||||
}
|
||||
|
||||
std::vector<Vector3> positions{};
|
||||
std::vector<Vector3> normals{};
|
||||
std::vector<int> indices{};
|
||||
unsigned char materialIndex{};
|
||||
|
||||
TriangleCullMode cullMode{ TriangleCullMode::BackFaceCulling };
|
||||
|
||||
Matrix rotationTransform{};
|
||||
Matrix translationTransform{};
|
||||
Matrix scaleTransform{};
|
||||
|
||||
std::vector<Vector3> transformedPositions{};
|
||||
std::vector<Vector3> transformedNormals{};
|
||||
|
||||
void Translate(const Vector3& translation)
|
||||
{
|
||||
translationTransform = Matrix::CreateTranslation(translation);
|
||||
}
|
||||
|
||||
void RotateY(float yaw)
|
||||
{
|
||||
rotationTransform = Matrix::CreateRotationY(yaw);
|
||||
}
|
||||
|
||||
void Scale(const Vector3& scale)
|
||||
{
|
||||
scaleTransform = Matrix::CreateScale(scale);
|
||||
}
|
||||
|
||||
void AppendTriangle(const Triangle& triangle, bool ignoreTransformUpdate = false)
|
||||
{
|
||||
int startIndex = static_cast<int>(positions.size());
|
||||
|
||||
positions.push_back(triangle.v0);
|
||||
positions.push_back(triangle.v1);
|
||||
positions.push_back(triangle.v2);
|
||||
|
||||
indices.push_back(startIndex);
|
||||
indices.push_back(++startIndex);
|
||||
indices.push_back(++startIndex);
|
||||
|
||||
normals.push_back(triangle.normal);
|
||||
|
||||
//Not ideal, but making sure all vertices are updated
|
||||
if (!ignoreTransformUpdate)
|
||||
UpdateTransforms();
|
||||
}
|
||||
|
||||
void CalculateNormals()
|
||||
{
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
}
|
||||
|
||||
void UpdateTransforms()
|
||||
{
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
//Calculate Final Transform
|
||||
//const auto finalTransform = ...
|
||||
|
||||
//Transform Positions (positions > transformedPositions)
|
||||
//...
|
||||
|
||||
//Transform Normals (normals > transformedNormals)
|
||||
//...
|
||||
}
|
||||
};
|
||||
#pragma endregion
|
||||
#pragma region LIGHT
|
||||
enum class LightType
|
||||
{
|
||||
Point,
|
||||
Directional
|
||||
};
|
||||
|
||||
struct Light
|
||||
{
|
||||
Vector3 origin{};
|
||||
Vector3 direction{};
|
||||
ColorRGB color{};
|
||||
float intensity{};
|
||||
|
||||
LightType type{};
|
||||
};
|
||||
#pragma endregion
|
||||
#pragma region MISC
|
||||
struct Ray
|
||||
{
|
||||
Vector3 origin{};
|
||||
Vector3 direction{};
|
||||
|
||||
float min{ 0.0001f };
|
||||
float max{ FLT_MAX };
|
||||
};
|
||||
|
||||
struct HitRecord
|
||||
{
|
||||
Vector3 origin{};
|
||||
Vector3 normal{};
|
||||
float t = FLT_MAX;
|
||||
|
||||
bool didHit{ false };
|
||||
unsigned char materialIndex{ 0 };
|
||||
};
|
||||
#pragma endregion
|
||||
}
|
||||
123
project/src/Material.h
Normal file
123
project/src/Material.h
Normal file
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
#include "Maths.h"
|
||||
#include "DataTypes.h"
|
||||
#include "BRDFs.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
#pragma region Material BASE
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material() = default;
|
||||
virtual ~Material() = default;
|
||||
|
||||
Material(const Material&) = delete;
|
||||
Material(Material&&) noexcept = delete;
|
||||
Material& operator=(const Material&) = delete;
|
||||
Material& operator=(Material&&) noexcept = delete;
|
||||
|
||||
/**
|
||||
* \brief Function used to calculate the correct color for the specific material and its parameters
|
||||
* \param hitRecord current hitrecord
|
||||
* \param l light direction
|
||||
* \param v view direction
|
||||
* \return color
|
||||
*/
|
||||
virtual ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) = 0;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Material SOLID COLOR
|
||||
//SOLID COLOR
|
||||
//===========
|
||||
class Material_SolidColor final : public Material
|
||||
{
|
||||
public:
|
||||
Material_SolidColor(const ColorRGB& color) : m_Color(color)
|
||||
{
|
||||
}
|
||||
|
||||
ColorRGB Shade(const HitRecord& hitRecord, const Vector3& l, const Vector3& v) override
|
||||
{
|
||||
return m_Color;
|
||||
}
|
||||
|
||||
private:
|
||||
ColorRGB m_Color{ colors::White };
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Material LAMBERT
|
||||
//LAMBERT
|
||||
//=======
|
||||
class Material_Lambert final : public Material
|
||||
{
|
||||
public:
|
||||
Material_Lambert(const ColorRGB& diffuseColor, float diffuseReflectance) :
|
||||
m_DiffuseColor(diffuseColor), m_DiffuseReflectance(diffuseReflectance) {}
|
||||
|
||||
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
ColorRGB m_DiffuseColor{ colors::White };
|
||||
float m_DiffuseReflectance{ 1.f }; //kd
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Material LAMBERT PHONG
|
||||
//LAMBERT-PHONG
|
||||
//=============
|
||||
class Material_LambertPhong final : public Material
|
||||
{
|
||||
public:
|
||||
Material_LambertPhong(const ColorRGB& diffuseColor, float kd, float ks, float phongExponent) :
|
||||
m_DiffuseColor(diffuseColor), m_DiffuseReflectance(kd), m_SpecularReflectance(ks),
|
||||
m_PhongExponent(phongExponent)
|
||||
{
|
||||
}
|
||||
|
||||
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
ColorRGB m_DiffuseColor{ colors::White };
|
||||
float m_DiffuseReflectance{ 0.5f }; //kd
|
||||
float m_SpecularReflectance{ 0.5f }; //ks
|
||||
float m_PhongExponent{ 1.f }; //Phong Exponent
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Material COOK TORRENCE
|
||||
//COOK TORRENCE
|
||||
class Material_CookTorrence final : public Material
|
||||
{
|
||||
public:
|
||||
Material_CookTorrence(const ColorRGB& albedo, float metalness, float roughness) :
|
||||
m_Albedo(albedo), m_Metalness(metalness), m_Roughness(roughness)
|
||||
{
|
||||
}
|
||||
|
||||
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
|
||||
{
|
||||
//todo: W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
ColorRGB m_Albedo{ 0.955f, 0.637f, 0.538f }; //Copper
|
||||
float m_Metalness{ 1.0f };
|
||||
float m_Roughness{ 0.1f }; // [1.0 > 0.0] >> [ROUGH > SMOOTH]
|
||||
};
|
||||
#pragma endregion
|
||||
}
|
||||
32
project/src/MathHelpers.h
Normal file
32
project/src/MathHelpers.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
#include <algorithm>
|
||||
|
||||
namespace dae
|
||||
{
|
||||
/* --- CONSTANTS --- */
|
||||
constexpr auto PI = 3.14159265358979323846f;
|
||||
constexpr auto PI_DIV_2 = 1.57079632679489661923f;
|
||||
constexpr auto PI_DIV_4 = 0.785398163397448309616f;
|
||||
constexpr auto PI_2 = 6.283185307179586476925f;
|
||||
constexpr auto PI_4 = 12.56637061435917295385f;
|
||||
|
||||
constexpr auto TO_DEGREES = (180.0f / PI);
|
||||
constexpr auto TO_RADIANS(PI / 180.0f);
|
||||
|
||||
inline float Square(float a)
|
||||
{
|
||||
return a * a;
|
||||
}
|
||||
|
||||
inline float Lerpf(float a, float b, float factor)
|
||||
{
|
||||
return ((1 - factor) * a) + (factor * b);
|
||||
}
|
||||
|
||||
inline bool AreEqual(float a, float b, float epsilon = FLT_EPSILON)
|
||||
{
|
||||
return abs(a - b) < epsilon;
|
||||
}
|
||||
}
|
||||
7
project/src/Maths.h
Normal file
7
project/src/Maths.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "Vector3.h"
|
||||
#include "Vector4.h"
|
||||
#include "Matrix.h"
|
||||
#include "ColorRGB.h"
|
||||
#include "MathHelpers.h"
|
||||
|
||||
214
project/src/Matrix.cpp
Normal file
214
project/src/Matrix.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
#include "Matrix.h"
|
||||
|
||||
namespace dae {
|
||||
Matrix::Matrix(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis, const Vector3& t) :
|
||||
Matrix({ xAxis, 0 }, { yAxis, 0 }, { zAxis, 0 }, { t, 1 })
|
||||
{
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Vector4& xAxis, const Vector4& yAxis, const Vector4& zAxis, const Vector4& t)
|
||||
{
|
||||
data[0] = xAxis;
|
||||
data[1] = yAxis;
|
||||
data[2] = zAxis;
|
||||
data[3] = t;
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Matrix& m)
|
||||
{
|
||||
data[0] = m[0];
|
||||
data[1] = m[1];
|
||||
data[2] = m[2];
|
||||
data[3] = m[3];
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformVector(const Vector3& v) const
|
||||
{
|
||||
return TransformVector(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformVector(float x, float y, float z) const
|
||||
{
|
||||
return Vector3{
|
||||
data[0].x * x + data[1].x * y + data[2].x * z,
|
||||
data[0].y * x + data[1].y * y + data[2].y * z,
|
||||
data[0].z * x + data[1].z * y + data[2].z * z
|
||||
};
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformPoint(const Vector3& p) const
|
||||
{
|
||||
return TransformPoint(p[0], p[1], p[2]);
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformPoint(float x, float y, float z) const
|
||||
{
|
||||
return Vector3{
|
||||
data[0].x * x + data[1].x * y + data[2].x * z + data[3].x,
|
||||
data[0].y * x + data[1].y * y + data[2].y * z + data[3].y,
|
||||
data[0].z * x + data[1].z * y + data[2].z * z + data[3].z,
|
||||
};
|
||||
}
|
||||
|
||||
const Matrix& Matrix::Transpose()
|
||||
{
|
||||
Matrix result{};
|
||||
for (int r{ 0 }; r < 4; ++r)
|
||||
{
|
||||
for (int c{ 0 }; c < 4; ++c)
|
||||
{
|
||||
result[r][c] = data[c][r];
|
||||
}
|
||||
}
|
||||
|
||||
data[0] = result[0];
|
||||
data[1] = result[1];
|
||||
data[2] = result[2];
|
||||
data[3] = result[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix Matrix::Transpose(const Matrix& m)
|
||||
{
|
||||
Matrix out{ m };
|
||||
out.Transpose();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetAxisX() const
|
||||
{
|
||||
return data[0];
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetAxisY() const
|
||||
{
|
||||
return data[1];
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetAxisZ() const
|
||||
{
|
||||
return data[2];
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetTranslation() const
|
||||
{
|
||||
return data[3];
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateTranslation(float x, float y, float z)
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateTranslation(const Vector3& t)
|
||||
{
|
||||
return { Vector3::UnitX, Vector3::UnitY, Vector3::UnitZ, t };
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationX(float pitch)
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationY(float yaw)
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationZ(float roll)
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotation(const Vector3& r)
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotation(float pitch, float yaw, float roll)
|
||||
{
|
||||
return CreateRotation({ pitch, yaw, roll });
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateScale(float sx, float sy, float sz)
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateScale(const Vector3& s)
|
||||
{
|
||||
return CreateScale(s[0], s[1], s[2]);
|
||||
}
|
||||
|
||||
#pragma region Operator Overloads
|
||||
Vector4& Matrix::operator[](int index)
|
||||
{
|
||||
assert(index <= 3 && index >= 0);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
Vector4 Matrix::operator[](int index) const
|
||||
{
|
||||
assert(index <= 3 && index >= 0);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
Matrix Matrix::operator*(const Matrix& m) const
|
||||
{
|
||||
Matrix result{};
|
||||
Matrix m_transposed = Transpose(m);
|
||||
|
||||
for (int r{ 0 }; r < 4; ++r)
|
||||
{
|
||||
for (int c{ 0 }; c < 4; ++c)
|
||||
{
|
||||
result[r][c] = Vector4::Dot(data[r], m_transposed[c]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const Matrix& Matrix::operator*=(const Matrix& m)
|
||||
{
|
||||
Matrix copy{ *this };
|
||||
Matrix m_transposed = Transpose(m);
|
||||
|
||||
for (int r{ 0 }; r < 4; ++r)
|
||||
{
|
||||
for (int c{ 0 }; c < 4; ++c)
|
||||
{
|
||||
data[r][c] = Vector4::Dot(copy[r], m_transposed[c]);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Matrix::operator==(const Matrix& m) const
|
||||
{
|
||||
return data[0] == m.data[0]
|
||||
&& data[1] == m.data[1]
|
||||
&& data[2] == m.data[2]
|
||||
&& data[3] == m.data[3];
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
67
project/src/Matrix.h
Normal file
67
project/src/Matrix.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include "Vector3.h"
|
||||
#include "Vector4.h"
|
||||
|
||||
namespace dae {
|
||||
struct Matrix
|
||||
{
|
||||
Matrix() = default;
|
||||
Matrix(
|
||||
const Vector3& xAxis,
|
||||
const Vector3& yAxis,
|
||||
const Vector3& zAxis,
|
||||
const Vector3& t);
|
||||
|
||||
Matrix(
|
||||
const Vector4& xAxis,
|
||||
const Vector4& yAxis,
|
||||
const Vector4& zAxis,
|
||||
const Vector4& t);
|
||||
|
||||
Matrix(const Matrix& m);
|
||||
|
||||
Vector3 TransformVector(const Vector3& v) const;
|
||||
Vector3 TransformVector(float x, float y, float z) const;
|
||||
Vector3 TransformPoint(const Vector3& p) const;
|
||||
Vector3 TransformPoint(float x, float y, float z) const;
|
||||
const Matrix& Transpose();
|
||||
|
||||
Vector3 GetAxisX() const;
|
||||
Vector3 GetAxisY() const;
|
||||
Vector3 GetAxisZ() const;
|
||||
Vector3 GetTranslation() const;
|
||||
|
||||
static Matrix CreateTranslation(float x, float y, float z);
|
||||
static Matrix CreateTranslation(const Vector3& t);
|
||||
static Matrix CreateRotationX(float pitch);
|
||||
static Matrix CreateRotationY(float yaw);
|
||||
static Matrix CreateRotationZ(float roll);
|
||||
static Matrix CreateRotation(float pitch, float yaw, float roll);
|
||||
static Matrix CreateRotation(const Vector3& r);
|
||||
static Matrix CreateScale(float sx, float sy, float sz);
|
||||
static Matrix CreateScale(const Vector3& s);
|
||||
static Matrix Transpose(const Matrix& m);
|
||||
|
||||
Vector4& operator[](int index);
|
||||
Vector4 operator[](int index) const;
|
||||
Matrix operator*(const Matrix& m) const;
|
||||
const Matrix& operator*=(const Matrix& m);
|
||||
bool operator==(const Matrix& m) const;
|
||||
|
||||
private:
|
||||
|
||||
//Row-Major Matrix
|
||||
Vector4 data[4]
|
||||
{
|
||||
{1,0,0,0}, //xAxis
|
||||
{0,1,0,0}, //yAxis
|
||||
{0,0,1,0}, //zAxis
|
||||
{0,0,0,1} //T
|
||||
};
|
||||
|
||||
// v0x v0y v0z v0w
|
||||
// v1x v1y v1z v1w
|
||||
// v2x v2y v2z v2w
|
||||
// v3x v3y v3z v3w
|
||||
};
|
||||
}
|
||||
58
project/src/Renderer.cpp
Normal file
58
project/src/Renderer.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//External includes
|
||||
#include "SDL.h"
|
||||
#include "SDL_surface.h"
|
||||
|
||||
//Project includes
|
||||
#include "Renderer.h"
|
||||
#include "Maths.h"
|
||||
#include "Matrix.h"
|
||||
#include "Material.h"
|
||||
#include "Scene.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
Renderer::Renderer(SDL_Window * pWindow) :
|
||||
m_pWindow(pWindow),
|
||||
m_pBuffer(SDL_GetWindowSurface(pWindow))
|
||||
{
|
||||
//Initialize
|
||||
SDL_GetWindowSize(pWindow, &m_Width, &m_Height);
|
||||
m_pBufferPixels = static_cast<uint32_t*>(m_pBuffer->pixels);
|
||||
}
|
||||
|
||||
void Renderer::Render(Scene* pScene) const
|
||||
{
|
||||
Camera& camera = pScene->GetCamera();
|
||||
auto& materials = pScene->GetMaterials();
|
||||
auto& lights = pScene->GetLights();
|
||||
|
||||
for (int px{}; px < m_Width; ++px)
|
||||
{
|
||||
for (int py{}; py < m_Height; ++py)
|
||||
{
|
||||
float gradient = px / static_cast<float>(m_Width);
|
||||
gradient += py / static_cast<float>(m_Width);
|
||||
gradient /= 2.0f;
|
||||
|
||||
ColorRGB finalColor{ gradient, gradient, gradient };
|
||||
|
||||
//Update Color in Buffer
|
||||
finalColor.MaxToOne();
|
||||
|
||||
m_pBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format,
|
||||
static_cast<uint8_t>(finalColor.r * 255),
|
||||
static_cast<uint8_t>(finalColor.g * 255),
|
||||
static_cast<uint8_t>(finalColor.b * 255));
|
||||
}
|
||||
}
|
||||
|
||||
//@END
|
||||
//Update SDL Surface
|
||||
SDL_UpdateWindowSurface(m_pWindow);
|
||||
}
|
||||
|
||||
bool Renderer::SaveBufferToImage() const
|
||||
{
|
||||
return SDL_SaveBMP(m_pBuffer, "RayTracing_Buffer.bmp");
|
||||
}
|
||||
35
project/src/Renderer.h
Normal file
35
project/src/Renderer.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace dae
|
||||
{
|
||||
class Scene;
|
||||
|
||||
class Renderer final
|
||||
{
|
||||
public:
|
||||
Renderer(SDL_Window* pWindow);
|
||||
~Renderer() = default;
|
||||
|
||||
Renderer(const Renderer&) = delete;
|
||||
Renderer(Renderer&&) noexcept = delete;
|
||||
Renderer& operator=(const Renderer&) = delete;
|
||||
Renderer& operator=(Renderer&&) noexcept = delete;
|
||||
|
||||
void Render(Scene* pScene) const;
|
||||
bool SaveBufferToImage() const;
|
||||
|
||||
private:
|
||||
SDL_Window* m_pWindow{};
|
||||
|
||||
SDL_Surface* m_pBuffer{};
|
||||
uint32_t* m_pBufferPixels{};
|
||||
|
||||
int m_Width{};
|
||||
int m_Height{};
|
||||
};
|
||||
}
|
||||
130
project/src/Scene.cpp
Normal file
130
project/src/Scene.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "Scene.h"
|
||||
#include "Utils.h"
|
||||
#include "Material.h"
|
||||
|
||||
namespace dae {
|
||||
|
||||
#pragma region Base Scene
|
||||
//Initialize Scene with Default Solid Color Material (RED)
|
||||
Scene::Scene() :
|
||||
m_Materials({ new Material_SolidColor({1,0,0}) })
|
||||
{
|
||||
m_SphereGeometries.reserve(32);
|
||||
m_PlaneGeometries.reserve(32);
|
||||
m_TriangleMeshGeometries.reserve(32);
|
||||
m_Lights.reserve(32);
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
{
|
||||
for (auto& pMaterial : m_Materials)
|
||||
{
|
||||
delete pMaterial;
|
||||
pMaterial = nullptr;
|
||||
}
|
||||
|
||||
m_Materials.clear();
|
||||
}
|
||||
|
||||
void dae::Scene::GetClosestHit(const Ray& ray, HitRecord& closestHit) const
|
||||
{
|
||||
//todo W1
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
}
|
||||
|
||||
bool Scene::DoesHit(const Ray& ray) const
|
||||
{
|
||||
//todo W2
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma region Scene Helpers
|
||||
Sphere* Scene::AddSphere(const Vector3& origin, float radius, unsigned char materialIndex)
|
||||
{
|
||||
Sphere s;
|
||||
s.origin = origin;
|
||||
s.radius = radius;
|
||||
s.materialIndex = materialIndex;
|
||||
|
||||
m_SphereGeometries.emplace_back(s);
|
||||
return &m_SphereGeometries.back();
|
||||
}
|
||||
|
||||
Plane* Scene::AddPlane(const Vector3& origin, const Vector3& normal, unsigned char materialIndex)
|
||||
{
|
||||
Plane p;
|
||||
p.origin = origin;
|
||||
p.normal = normal;
|
||||
p.materialIndex = materialIndex;
|
||||
|
||||
m_PlaneGeometries.emplace_back(p);
|
||||
return &m_PlaneGeometries.back();
|
||||
}
|
||||
|
||||
TriangleMesh* Scene::AddTriangleMesh(TriangleCullMode cullMode, unsigned char materialIndex)
|
||||
{
|
||||
TriangleMesh m{};
|
||||
m.cullMode = cullMode;
|
||||
m.materialIndex = materialIndex;
|
||||
|
||||
m_TriangleMeshGeometries.emplace_back(m);
|
||||
return &m_TriangleMeshGeometries.back();
|
||||
}
|
||||
|
||||
Light* Scene::AddPointLight(const Vector3& origin, float intensity, const ColorRGB& color)
|
||||
{
|
||||
Light l;
|
||||
l.origin = origin;
|
||||
l.intensity = intensity;
|
||||
l.color = color;
|
||||
l.type = LightType::Point;
|
||||
|
||||
m_Lights.emplace_back(l);
|
||||
return &m_Lights.back();
|
||||
}
|
||||
|
||||
Light* Scene::AddDirectionalLight(const Vector3& direction, float intensity, const ColorRGB& color)
|
||||
{
|
||||
Light l;
|
||||
l.direction = direction;
|
||||
l.intensity = intensity;
|
||||
l.color = color;
|
||||
l.type = LightType::Directional;
|
||||
|
||||
m_Lights.emplace_back(l);
|
||||
return &m_Lights.back();
|
||||
}
|
||||
|
||||
unsigned char Scene::AddMaterial(Material* pMaterial)
|
||||
{
|
||||
m_Materials.push_back(pMaterial);
|
||||
return static_cast<unsigned char>(m_Materials.size() - 1);
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SCENE W1
|
||||
void Scene_W1::Initialize()
|
||||
{
|
||||
//default: Material id0 >> SolidColor Material (RED)
|
||||
constexpr unsigned char matId_Solid_Red = 0;
|
||||
const unsigned char matId_Solid_Blue = AddMaterial(new Material_SolidColor{ colors::Blue });
|
||||
|
||||
const unsigned char matId_Solid_Yellow = AddMaterial(new Material_SolidColor{ colors::Yellow });
|
||||
const unsigned char matId_Solid_Green = AddMaterial(new Material_SolidColor{ colors::Green });
|
||||
const unsigned char matId_Solid_Magenta = AddMaterial(new Material_SolidColor{ colors::Magenta });
|
||||
|
||||
//Spheres
|
||||
AddSphere({ -25.f, 0.f, 100.f }, 50.f, matId_Solid_Red);
|
||||
AddSphere({ 25.f, 0.f, 100.f }, 50.f, matId_Solid_Blue);
|
||||
|
||||
//Plane
|
||||
AddPlane({ -75.f, 0.f, 0.f }, { 1.f, 0.f,0.f }, matId_Solid_Green);
|
||||
AddPlane({ 75.f, 0.f, 0.f }, { -1.f, 0.f,0.f }, matId_Solid_Green);
|
||||
AddPlane({ 0.f, -75.f, 0.f }, { 0.f, 1.f,0.f }, matId_Solid_Yellow);
|
||||
AddPlane({ 0.f, 75.f, 0.f }, { 0.f, -1.f,0.f }, matId_Solid_Yellow);
|
||||
AddPlane({ 0.f, 0.f, 125.f }, { 0.f, 0.f,-1.f }, matId_Solid_Magenta);
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
80
project/src/Scene.h
Normal file
80
project/src/Scene.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Maths.h"
|
||||
#include "DataTypes.h"
|
||||
#include "Camera.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
//Forward Declarations
|
||||
class Timer;
|
||||
class Material;
|
||||
struct Plane;
|
||||
struct Sphere;
|
||||
struct Light;
|
||||
|
||||
//Scene Base Class
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
Scene();
|
||||
virtual ~Scene();
|
||||
|
||||
Scene(const Scene&) = delete;
|
||||
Scene(Scene&&) noexcept = delete;
|
||||
Scene& operator=(const Scene&) = delete;
|
||||
Scene& operator=(Scene&&) noexcept = delete;
|
||||
|
||||
virtual void Initialize() = 0;
|
||||
virtual void Update(dae::Timer* pTimer)
|
||||
{
|
||||
m_Camera.Update(pTimer);
|
||||
}
|
||||
|
||||
Camera& GetCamera() { return m_Camera; }
|
||||
void GetClosestHit(const Ray& ray, HitRecord& closestHit) const;
|
||||
bool DoesHit(const Ray& ray) const;
|
||||
|
||||
const std::vector<Plane>& GetPlaneGeometries() const { return m_PlaneGeometries; }
|
||||
const std::vector<Sphere>& GetSphereGeometries() const { return m_SphereGeometries; }
|
||||
const std::vector<Light>& GetLights() const { return m_Lights; }
|
||||
const std::vector<Material*> GetMaterials() const { return m_Materials; }
|
||||
|
||||
protected:
|
||||
std::string sceneName;
|
||||
|
||||
std::vector<Plane> m_PlaneGeometries{};
|
||||
std::vector<Sphere> m_SphereGeometries{};
|
||||
std::vector<TriangleMesh> m_TriangleMeshGeometries{};
|
||||
std::vector<Light> m_Lights{};
|
||||
std::vector<Material*> m_Materials{};
|
||||
|
||||
Camera m_Camera{};
|
||||
|
||||
Sphere* AddSphere(const Vector3& origin, float radius, unsigned char materialIndex = 0);
|
||||
Plane* AddPlane(const Vector3& origin, const Vector3& normal, unsigned char materialIndex = 0);
|
||||
TriangleMesh* AddTriangleMesh(TriangleCullMode cullMode, unsigned char materialIndex = 0);
|
||||
|
||||
Light* AddPointLight(const Vector3& origin, float intensity, const ColorRGB& color);
|
||||
Light* AddDirectionalLight(const Vector3& direction, float intensity, const ColorRGB& color);
|
||||
unsigned char AddMaterial(Material* pMaterial);
|
||||
};
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++
|
||||
//WEEK 1 Test Scene
|
||||
class Scene_W1 final : public Scene
|
||||
{
|
||||
public:
|
||||
Scene_W1() = default;
|
||||
~Scene_W1() override = default;
|
||||
|
||||
Scene_W1(const Scene_W1&) = delete;
|
||||
Scene_W1(Scene_W1&&) noexcept = delete;
|
||||
Scene_W1& operator=(const Scene_W1&) = delete;
|
||||
Scene_W1& operator=(Scene_W1&&) noexcept = delete;
|
||||
|
||||
void Initialize() override;
|
||||
};
|
||||
}
|
||||
144
project/src/Timer.cpp
Normal file
144
project/src/Timer.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "Timer.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <float.h>
|
||||
|
||||
#include "SDL.h"
|
||||
using namespace dae;
|
||||
|
||||
Timer::Timer()
|
||||
{
|
||||
const uint64_t countsPerSecond = SDL_GetPerformanceFrequency();
|
||||
m_SecondsPerCount = 1.0f / static_cast<float>(countsPerSecond);
|
||||
}
|
||||
|
||||
void Timer::Reset()
|
||||
{
|
||||
const uint64_t currentTime = SDL_GetPerformanceCounter();
|
||||
|
||||
m_BaseTime = currentTime;
|
||||
m_PreviousTime = currentTime;
|
||||
m_StopTime = 0;
|
||||
m_FPSTimer = 0.0f;
|
||||
m_FPSCount = 0;
|
||||
m_IsStopped = false;
|
||||
}
|
||||
|
||||
void Timer::Start()
|
||||
{
|
||||
const uint64_t startTime = SDL_GetPerformanceCounter();
|
||||
|
||||
if (m_IsStopped)
|
||||
{
|
||||
m_PausedTime += (startTime - m_StopTime);
|
||||
|
||||
m_PreviousTime = startTime;
|
||||
m_StopTime = 0;
|
||||
m_IsStopped = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::StartBenchmark(int numFrames)
|
||||
{
|
||||
if (m_BenchmarkActive)
|
||||
{
|
||||
std::cout << "(Benchmark already running)";
|
||||
return;
|
||||
}
|
||||
|
||||
m_BenchmarkActive = true;
|
||||
|
||||
m_BenchmarkAvg = 0.f;
|
||||
m_BenchmarkHigh = FLT_MIN;
|
||||
m_BenchmarkLow = FLT_MAX;
|
||||
|
||||
m_BenchmarkFrames = numFrames;
|
||||
m_BenchmarkCurrFrame = 0;
|
||||
|
||||
m_Benchmarks.clear();
|
||||
m_Benchmarks.resize(m_BenchmarkFrames);
|
||||
|
||||
std::cout << "**BENCHMARK STARTED**\n";
|
||||
}
|
||||
|
||||
void Timer::Update()
|
||||
{
|
||||
if (m_IsStopped)
|
||||
{
|
||||
m_FPS = 0;
|
||||
m_ElapsedTime = 0.0f;
|
||||
m_TotalTime = (float)(((m_StopTime - m_PausedTime) - m_BaseTime) * m_BaseTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t currentTime = SDL_GetPerformanceCounter();
|
||||
m_CurrentTime = currentTime;
|
||||
|
||||
m_ElapsedTime = (float)((m_CurrentTime - m_PreviousTime) * m_SecondsPerCount);
|
||||
m_PreviousTime = m_CurrentTime;
|
||||
|
||||
if (m_ElapsedTime < 0.0f)
|
||||
m_ElapsedTime = 0.0f;
|
||||
|
||||
if (m_ForceElapsedUpperBound && m_ElapsedTime > m_ElapsedUpperBound)
|
||||
{
|
||||
m_ElapsedTime = m_ElapsedUpperBound;
|
||||
}
|
||||
|
||||
m_TotalTime = (float)(((m_CurrentTime - m_PausedTime) - m_BaseTime) * m_SecondsPerCount);
|
||||
|
||||
//FPS LOGIC
|
||||
m_FPSTimer += m_ElapsedTime;
|
||||
++m_FPSCount;
|
||||
if (m_FPSTimer >= 1.0f)
|
||||
{
|
||||
m_dFPS = m_FPSCount / m_FPSTimer;
|
||||
m_FPS = m_FPSCount;
|
||||
m_FPSCount = 0;
|
||||
m_FPSTimer = 0.0f;
|
||||
|
||||
if (m_BenchmarkActive)
|
||||
{
|
||||
m_Benchmarks[m_BenchmarkCurrFrame] = m_dFPS;
|
||||
|
||||
m_BenchmarkLow = std::min(m_BenchmarkLow, m_dFPS);
|
||||
m_BenchmarkHigh = std::max(m_BenchmarkHigh, m_dFPS);
|
||||
|
||||
++m_BenchmarkCurrFrame;
|
||||
if (m_BenchmarkCurrFrame >= m_BenchmarkFrames)
|
||||
{
|
||||
m_BenchmarkActive = false;
|
||||
m_BenchmarkAvg = std::accumulate(m_Benchmarks.begin(), m_Benchmarks.end(), 0.f) / float(m_BenchmarkFrames);
|
||||
|
||||
//print
|
||||
std::cout << "**BENCHMARK FINISHED**\n";
|
||||
std::cout << ">> HIGH = " << m_BenchmarkHigh << std::endl;
|
||||
std::cout << ">> LOW = " << m_BenchmarkLow << std::endl;
|
||||
std::cout << ">> AVG = " << m_BenchmarkAvg << std::endl;
|
||||
|
||||
//file save
|
||||
std::ofstream fileStream("benchmark.txt");
|
||||
fileStream << "FRAMES = " << m_BenchmarkCurrFrame << std::endl;
|
||||
fileStream << "HIGH = " << m_BenchmarkHigh << std::endl;
|
||||
fileStream << "LOW = " << m_BenchmarkLow << std::endl;
|
||||
fileStream << "AVG = " << m_BenchmarkAvg << std::endl;
|
||||
fileStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::Stop()
|
||||
{
|
||||
if (!m_IsStopped)
|
||||
{
|
||||
const uint64_t currentTime = SDL_GetPerformanceCounter();
|
||||
|
||||
m_StopTime = currentTime;
|
||||
m_IsStopped = true;
|
||||
}
|
||||
}
|
||||
61
project/src/Timer.h
Normal file
61
project/src/Timer.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
//Standard includes
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace dae
|
||||
{
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer();
|
||||
virtual ~Timer() = default;
|
||||
|
||||
Timer(const Timer&) = delete;
|
||||
Timer(Timer&&) noexcept = delete;
|
||||
Timer& operator=(const Timer&) = delete;
|
||||
Timer& operator=(Timer&&) noexcept = delete;
|
||||
|
||||
void StartBenchmark(int numFrames = 10);
|
||||
|
||||
void Reset();
|
||||
void Start();
|
||||
void Update();
|
||||
void Stop();
|
||||
|
||||
uint32_t GetFPS() const { return m_FPS; };
|
||||
float GetdFPS() const { return m_dFPS; };
|
||||
float GetElapsed() const { return m_ElapsedTime; };
|
||||
float GetTotal() const { return m_TotalTime; };
|
||||
bool IsRunning() const { return !m_IsStopped; };
|
||||
|
||||
private:
|
||||
uint64_t m_BaseTime = 0;
|
||||
uint64_t m_PausedTime = 0;
|
||||
uint64_t m_StopTime = 0;
|
||||
uint64_t m_PreviousTime = 0;
|
||||
uint64_t m_CurrentTime = 0;
|
||||
|
||||
uint32_t m_FPS = 0;
|
||||
float m_dFPS = 0.0f;
|
||||
uint32_t m_FPSCount = 0;
|
||||
|
||||
float m_TotalTime = 0.0f;
|
||||
float m_ElapsedTime = 0.0f;
|
||||
float m_SecondsPerCount = 0.0f;
|
||||
float m_ElapsedUpperBound = 0.03f;
|
||||
float m_FPSTimer = 0.0f;
|
||||
|
||||
bool m_IsStopped = true;
|
||||
bool m_ForceElapsedUpperBound = false;
|
||||
|
||||
bool m_BenchmarkActive = false;
|
||||
float m_BenchmarkHigh{ 0.f };
|
||||
float m_BenchmarkLow{ 0.f };
|
||||
float m_BenchmarkAvg{ 0.f };
|
||||
int m_BenchmarkFrames{ 0 };
|
||||
int m_BenchmarkCurrFrame{ 0 };
|
||||
std::vector<float> m_Benchmarks{};
|
||||
};
|
||||
}
|
||||
163
project/src/Utils.h
Normal file
163
project/src/Utils.h
Normal file
@@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include "Maths.h"
|
||||
#include "DataTypes.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
namespace GeometryUtils
|
||||
{
|
||||
#pragma region Sphere HitTest
|
||||
//SPHERE HIT-TESTS
|
||||
inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
||||
{
|
||||
//todo W1
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray)
|
||||
{
|
||||
HitRecord temp{};
|
||||
return HitTest_Sphere(sphere, ray, temp, true);
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Plane HitTest
|
||||
//PLANE HIT-TESTS
|
||||
inline bool HitTest_Plane(const Plane& plane, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
||||
{
|
||||
//todo W1
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HitTest_Plane(const Plane& plane, const Ray& ray)
|
||||
{
|
||||
HitRecord temp{};
|
||||
return HitTest_Plane(plane, ray, temp, true);
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Triangle HitTest
|
||||
//TRIANGLE HIT-TESTS
|
||||
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
||||
{
|
||||
//todo W5
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray)
|
||||
{
|
||||
HitRecord temp{};
|
||||
return HitTest_Triangle(triangle, ray, temp, true);
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region TriangeMesh HitTest
|
||||
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
||||
{
|
||||
//todo W5
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray)
|
||||
{
|
||||
HitRecord temp{};
|
||||
return HitTest_TriangleMesh(mesh, ray, temp, true);
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
namespace LightUtils
|
||||
{
|
||||
//Direction from target to light
|
||||
inline Vector3 GetDirectionToLight(const Light& light, const Vector3 origin)
|
||||
{
|
||||
//todo W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
inline ColorRGB GetRadiance(const Light& light, const Vector3& target)
|
||||
{
|
||||
//todo W3
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
//Just parses vertices and indices
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4505) //Warning unreferenced local function
|
||||
static bool ParseOBJ(const std::string& filename, std::vector<Vector3>& positions, std::vector<Vector3>& normals, std::vector<int>& indices)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
std::string sCommand;
|
||||
// start a while iteration ending when the end of file is reached (ios::eof)
|
||||
while (!file.eof())
|
||||
{
|
||||
//read the first word of the string, use the >> operator (istream::operator>>)
|
||||
file >> sCommand;
|
||||
//use conditional statements to process the different commands
|
||||
if (sCommand == "#")
|
||||
{
|
||||
// Ignore Comment
|
||||
}
|
||||
else if (sCommand == "v")
|
||||
{
|
||||
//Vertex
|
||||
float x, y, z;
|
||||
file >> x >> y >> z;
|
||||
positions.push_back({ x, y, z });
|
||||
}
|
||||
else if (sCommand == "f")
|
||||
{
|
||||
float i0, i1, i2;
|
||||
file >> i0 >> i1 >> i2;
|
||||
|
||||
indices.push_back((int)i0 - 1);
|
||||
indices.push_back((int)i1 - 1);
|
||||
indices.push_back((int)i2 - 1);
|
||||
}
|
||||
//read till end of line and ignore all remaining chars
|
||||
file.ignore(1000, '\n');
|
||||
|
||||
if (file.eof())
|
||||
break;
|
||||
}
|
||||
|
||||
//Precompute normals
|
||||
for (uint64_t index = 0; index < indices.size(); index += 3)
|
||||
{
|
||||
uint32_t i0 = indices[index];
|
||||
uint32_t i1 = indices[index + 1];
|
||||
uint32_t i2 = indices[index + 2];
|
||||
|
||||
Vector3 edgeV0V1 = positions[i1] - positions[i0];
|
||||
Vector3 edgeV0V2 = positions[i2] - positions[i0];
|
||||
Vector3 normal = Vector3::Cross(edgeV0V1, edgeV0V2);
|
||||
|
||||
if (std::isnan(normal.x))
|
||||
{
|
||||
int k = 0;
|
||||
}
|
||||
|
||||
normal.Normalize();
|
||||
if (std::isnan(normal.x))
|
||||
{
|
||||
int k = 0;
|
||||
}
|
||||
|
||||
normals.push_back(normal);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
}
|
||||
}
|
||||
170
project/src/Vector3.cpp
Normal file
170
project/src/Vector3.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "Vector3.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "MathHelpers.h"
|
||||
#include "Vector4.h"
|
||||
|
||||
|
||||
namespace dae {
|
||||
const Vector3 Vector3::UnitX = Vector3{ 1, 0, 0 };
|
||||
const Vector3 Vector3::UnitY = Vector3{ 0, 1, 0 };
|
||||
const Vector3 Vector3::UnitZ = Vector3{ 0, 0, 1 };
|
||||
const Vector3 Vector3::Zero = Vector3{ 0, 0, 0 };
|
||||
|
||||
Vector3::Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
|
||||
Vector3::Vector3(const Vector4& v) : x(v.x), y(v.y), z(v.z) {}
|
||||
|
||||
Vector3::Vector3(const Vector3& from, const Vector3& to) : x(to.x - from.x), y(to.y - from.y), z(to.z - from.z) {}
|
||||
|
||||
float Vector3::Magnitude() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
float Vector3::SqrMagnitude() const
|
||||
{
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
float Vector3::Normalize()
|
||||
{
|
||||
const float m = Magnitude();
|
||||
x /= m;
|
||||
y /= m;
|
||||
z /= m;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
Vector3 Vector3::Normalized() const
|
||||
{
|
||||
const float m = Magnitude();
|
||||
return { x / m, y / m, z / m };
|
||||
}
|
||||
|
||||
float Vector3::Dot(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
//todo W1
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
//todo W1
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
Vector3 Vector3::Project(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
return (v2 * (Dot(v1, v2) / Dot(v2, v2)));
|
||||
}
|
||||
|
||||
Vector3 Vector3::Reject(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
return (v1 - v2 * (Dot(v1, v2) / Dot(v2, v2)));
|
||||
}
|
||||
|
||||
Vector3 Vector3::Reflect(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
return v1 - (2.f * Vector3::Dot(v1, v2) * v2);
|
||||
}
|
||||
|
||||
Vector4 Vector3::ToPoint4() const
|
||||
{
|
||||
return { x, y, z, 1 };
|
||||
}
|
||||
|
||||
Vector4 Vector3::ToVector4() const
|
||||
{
|
||||
return { x, y, z, 0 };
|
||||
}
|
||||
|
||||
#pragma region Operator Overloads
|
||||
Vector3 Vector3::operator*(float scale) const
|
||||
{
|
||||
return { x * scale, y * scale, z * scale };
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator/(float scale) const
|
||||
{
|
||||
return { x / scale, y / scale, z / scale };
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator+(const Vector3& v) const
|
||||
{
|
||||
return { x + v.x, y + v.y, z + v.z };
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-(const Vector3& v) const
|
||||
{
|
||||
return { x - v.x, y - v.y, z - v.z };
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-() const
|
||||
{
|
||||
return { -x ,-y,-z };
|
||||
}
|
||||
|
||||
Vector3& Vector3::operator*=(float scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
z *= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3& Vector3::operator/=(float scale)
|
||||
{
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
z /= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3& Vector3::operator-=(const Vector3& v)
|
||||
{
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3& Vector3::operator+=(const Vector3& v)
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float& Vector3::operator[](int index)
|
||||
{
|
||||
assert(index <= 2 && index >= 0);
|
||||
|
||||
if (index == 0) return x;
|
||||
if (index == 1) return y;
|
||||
return z;
|
||||
}
|
||||
|
||||
float Vector3::operator[](int index) const
|
||||
{
|
||||
assert(index <= 2 && index >= 0);
|
||||
|
||||
if (index == 0) return x;
|
||||
if (index == 1) return y;
|
||||
return z;
|
||||
}
|
||||
|
||||
bool Vector3::operator==(const Vector3& v) const
|
||||
{
|
||||
return AreEqual(x, v.x) && AreEqual(y, v.y) && AreEqual(z, v.z);
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
58
project/src/Vector3.h
Normal file
58
project/src/Vector3.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct Vector4;
|
||||
struct Vector3
|
||||
{
|
||||
float x{};
|
||||
float y{};
|
||||
float z{};
|
||||
|
||||
Vector3() = default;
|
||||
Vector3(float _x, float _y, float _z);
|
||||
Vector3(const Vector3& from, const Vector3& to);
|
||||
Vector3(const Vector4& v);
|
||||
|
||||
float Magnitude() const;
|
||||
float SqrMagnitude() const;
|
||||
float Normalize();
|
||||
Vector3 Normalized() const;
|
||||
|
||||
static float Dot(const Vector3& v1, const Vector3& v2);
|
||||
static Vector3 Cross(const Vector3& v1, const Vector3& v2);
|
||||
static Vector3 Project(const Vector3& v1, const Vector3& v2);
|
||||
static Vector3 Reject(const Vector3& v1, const Vector3& v2);
|
||||
static Vector3 Reflect(const Vector3& v1, const Vector3& v2);
|
||||
static Vector3 Lico(float f1, const Vector3& v1, float f2, const Vector3& v2, float f3, const Vector3& v3);
|
||||
|
||||
Vector4 ToPoint4() const;
|
||||
Vector4 ToVector4() const;
|
||||
|
||||
//Member Operators
|
||||
Vector3 operator*(float scale) const;
|
||||
Vector3 operator/(float scale) const;
|
||||
Vector3 operator+(const Vector3& v) const;
|
||||
Vector3 operator-(const Vector3& v) const;
|
||||
Vector3 operator-() const;
|
||||
//Vector3& operator-();
|
||||
Vector3& operator+=(const Vector3& v);
|
||||
Vector3& operator-=(const Vector3& v);
|
||||
Vector3& operator/=(float scale);
|
||||
Vector3& operator*=(float scale);
|
||||
float& operator[](int index);
|
||||
float operator[](int index) const;
|
||||
bool operator==(const Vector3& v) const;
|
||||
|
||||
static const Vector3 UnitX;
|
||||
static const Vector3 UnitY;
|
||||
static const Vector3 UnitZ;
|
||||
static const Vector3 Zero;
|
||||
};
|
||||
|
||||
//Global Operators
|
||||
inline Vector3 operator*(float scale, const Vector3& v)
|
||||
{
|
||||
return { v.x * scale, v.y * scale, v.z * scale };
|
||||
}
|
||||
}
|
||||
100
project/src/Vector4.cpp
Normal file
100
project/src/Vector4.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "Vector3.h"
|
||||
#include "Vector4.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "MathHelpers.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
Vector4::Vector4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) {}
|
||||
Vector4::Vector4(const Vector3& v, float _w) : x(v.x), y(v.y), z(v.z), w(_w) {}
|
||||
|
||||
float Vector4::Magnitude() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y + z * z + w * w);
|
||||
}
|
||||
|
||||
float Vector4::SqrMagnitude() const
|
||||
{
|
||||
return x * x + y * y + z * z + w * w;
|
||||
}
|
||||
|
||||
float Vector4::Normalize()
|
||||
{
|
||||
const float m = Magnitude();
|
||||
x /= m;
|
||||
y /= m;
|
||||
z /= m;
|
||||
w /= m;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
Vector4 Vector4::Normalized() const
|
||||
{
|
||||
const float m = Magnitude();
|
||||
return { x / m, y / m, z / m, w / m };
|
||||
}
|
||||
|
||||
float Vector4::Dot(const Vector4& v1, const Vector4& v2)
|
||||
{
|
||||
//todo W1
|
||||
throw std::runtime_error("Not Implemented Yet");
|
||||
return {};
|
||||
}
|
||||
|
||||
#pragma region Operator Overloads
|
||||
Vector4 Vector4::operator*(float scale) const
|
||||
{
|
||||
return { x * scale, y * scale, z * scale, w * scale };
|
||||
}
|
||||
|
||||
Vector4 Vector4::operator+(const Vector4& v) const
|
||||
{
|
||||
return { x + v.x, y + v.y, z + v.z, w + v.w };
|
||||
}
|
||||
|
||||
Vector4 Vector4::operator-(const Vector4& v) const
|
||||
{
|
||||
return { x - v.x, y - v.y, z - v.z, w - v.w };
|
||||
}
|
||||
|
||||
Vector4& Vector4::operator+=(const Vector4& v)
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
w += v.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float& Vector4::operator[](int index)
|
||||
{
|
||||
assert(index <= 3 && index >= 0);
|
||||
|
||||
if (index == 0)return x;
|
||||
if (index == 1)return y;
|
||||
if (index == 2)return z;
|
||||
return w;
|
||||
}
|
||||
|
||||
float Vector4::operator[](int index) const
|
||||
{
|
||||
assert(index <= 3 && index >= 0);
|
||||
|
||||
if (index == 0)return x;
|
||||
if (index == 1)return y;
|
||||
if (index == 2)return z;
|
||||
return w;
|
||||
}
|
||||
|
||||
bool Vector4::operator==(const Vector4& v) const
|
||||
{
|
||||
return AreEqual(x, v.x, .000001f) && AreEqual(y, v.y, .000001f) && AreEqual(z, v.z, .000001f) && AreEqual(w, v.w, .000001f);
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
33
project/src/Vector4.h
Normal file
33
project/src/Vector4.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct Vector3;
|
||||
struct Vector4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
|
||||
Vector4() = default;
|
||||
Vector4(float _x, float _y, float _z, float _w);
|
||||
Vector4(const Vector3& v, float _w);
|
||||
|
||||
float Magnitude() const;
|
||||
float SqrMagnitude() const;
|
||||
float Normalize();
|
||||
Vector4 Normalized() const;
|
||||
|
||||
static float Dot(const Vector4& v1, const Vector4& v2);
|
||||
|
||||
// operator overloading
|
||||
Vector4 operator*(float scale) const;
|
||||
Vector4 operator+(const Vector4& v) const;
|
||||
Vector4 operator-(const Vector4& v) const;
|
||||
Vector4& operator+=(const Vector4& v);
|
||||
float& operator[](int index);
|
||||
float operator[](int index) const;
|
||||
bool operator==(const Vector4& v) const;
|
||||
};
|
||||
}
|
||||
114
project/src/main.cpp
Normal file
114
project/src/main.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
//External includes
|
||||
#ifdef ENABLE_VLD
|
||||
#include "vld.h"
|
||||
#endif
|
||||
#include "SDL.h"
|
||||
#include "SDL_surface.h"
|
||||
#undef main
|
||||
|
||||
//Standard includes
|
||||
#include <iostream>
|
||||
|
||||
//Project includes
|
||||
#include "Timer.h"
|
||||
#include "Renderer.h"
|
||||
#include "Scene.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
void ShutDown(SDL_Window* pWindow)
|
||||
{
|
||||
SDL_DestroyWindow(pWindow);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
int main(int argc, char* args[])
|
||||
{
|
||||
//Unreferenced parameters
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
//Create window + surfaces
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
const uint32_t width = 640;
|
||||
const uint32_t height = 480;
|
||||
|
||||
SDL_Window* pWindow = SDL_CreateWindow(
|
||||
"RayTracer - **Insert Name**",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width, height, 0);
|
||||
|
||||
if (!pWindow)
|
||||
return 1;
|
||||
|
||||
//Initialize "framework"
|
||||
const auto pTimer = new Timer();
|
||||
const auto pRenderer = new Renderer(pWindow);
|
||||
|
||||
const auto pScene = new Scene_W1();
|
||||
pScene->Initialize();
|
||||
|
||||
//Start loop
|
||||
pTimer->Start();
|
||||
|
||||
// Start Benchmark
|
||||
// pTimer->StartBenchmark();
|
||||
|
||||
float printTimer = 0.f;
|
||||
bool isLooping = true;
|
||||
bool takeScreenshot = false;
|
||||
while (isLooping)
|
||||
{
|
||||
//--------- Get input events ---------
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e))
|
||||
{
|
||||
switch (e.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
isLooping = false;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_X)
|
||||
takeScreenshot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------- Update ---------
|
||||
pScene->Update(pTimer);
|
||||
|
||||
//--------- Render ---------
|
||||
pRenderer->Render(pScene);
|
||||
|
||||
//--------- Timer ---------
|
||||
pTimer->Update();
|
||||
printTimer += pTimer->GetElapsed();
|
||||
if (printTimer >= 1.f)
|
||||
{
|
||||
printTimer = 0.f;
|
||||
std::cout << "dFPS: " << pTimer->GetdFPS() << std::endl;
|
||||
}
|
||||
|
||||
//Save screenshot after full render
|
||||
if (takeScreenshot)
|
||||
{
|
||||
if (!pRenderer->SaveBufferToImage())
|
||||
std::cout << "Screenshot saved!" << std::endl;
|
||||
else
|
||||
std::cout << "Something went wrong. Screenshot not saved!" << std::endl;
|
||||
takeScreenshot = false;
|
||||
}
|
||||
}
|
||||
pTimer->Stop();
|
||||
|
||||
//Shutdown "framework"
|
||||
delete pScene;
|
||||
delete pRenderer;
|
||||
delete pTimer;
|
||||
|
||||
ShutDown(pWindow);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user