Batman
This commit is contained in:
190
project/src/Camera.cpp
Normal file
190
project/src/Camera.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// Created by Bram on 11/12/2024.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "Camera.h"
|
||||
#include "GamePadController.h"
|
||||
|
||||
dae::Camera::Camera(const dae::Vector3 &_origin, float _fovAngle) :
|
||||
origin{_origin},
|
||||
fovAngle{_fovAngle} {
|
||||
SetFOV(_fovAngle);
|
||||
}
|
||||
|
||||
void dae::Camera::Initialize(float _fovAngle, dae::Vector3 _origin, float _aspect) {
|
||||
fovAngle = _fovAngle;
|
||||
fov = tanf((fovAngle * TO_RADIANS) / 2.f);
|
||||
aspect = _aspect;
|
||||
|
||||
origin = _origin;
|
||||
}
|
||||
|
||||
void dae::Camera::SetFOV(float _fovAngle) {
|
||||
fovAngle = _fovAngle;
|
||||
fov = tanf((fovAngle * TO_RADIANS) / 2.f);
|
||||
}
|
||||
|
||||
|
||||
void dae::Camera::CalculateViewMatrix() {
|
||||
|
||||
viewMatrix = Matrix::CreateLookAtLH(origin, origin + forward, Vector3::UnitY);
|
||||
Matrix temp = viewMatrix;
|
||||
|
||||
invViewMatrix = temp.Inverse();
|
||||
|
||||
right = invViewMatrix.GetAxisX();
|
||||
up = invViewMatrix.GetAxisY();
|
||||
forward = invViewMatrix.GetAxisZ();
|
||||
}
|
||||
|
||||
void dae::Camera::CalculateProjectionMatrix() {
|
||||
//TODO W3
|
||||
|
||||
ProjectionMatrix = Matrix::CreatePerspectiveFovLH(fov, aspect, zNear, zFar);
|
||||
//DirectX Implementation => https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovlh
|
||||
}
|
||||
|
||||
void dae::Camera::Update(const dae::Timer *pTimer) {
|
||||
const float deltaTime = pTimer->GetElapsed();
|
||||
|
||||
//Keyboard Input
|
||||
const uint8_t *pKeyboardState = SDL_GetKeyboardState(nullptr);
|
||||
|
||||
Vector3 zDirection{0.f, 0.f, 0.f};
|
||||
const Vector3 xDirection{0.f, 0.f, 0.f};
|
||||
const Vector3 yDirection{0.f, 0.f, 0.f};
|
||||
|
||||
float MovementSpeed{10.f};
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_LSHIFT]) {
|
||||
MovementSpeed *= 2;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_W]) {
|
||||
origin += forward * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_A]) {
|
||||
origin -= right * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_S]) {
|
||||
origin -= forward * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_D]) {
|
||||
origin += right * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_E]) {
|
||||
origin += up * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_Q]) {
|
||||
origin -= up * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
bool rightStickMoved = false;
|
||||
constexpr float DEADZONE = 5000;
|
||||
|
||||
if (GamePadController::GetInstance().isAnyControllerConnected()) {
|
||||
|
||||
//Controller
|
||||
float LeftStickX = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
float LeftStickY = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
|
||||
|
||||
float RightStickX = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
float RightStickY = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_RIGHTY);
|
||||
|
||||
if (std::abs(LeftStickX) > DEADZONE) {
|
||||
float correctedValue = remap(LeftStickX, -32767.f, 32767.f, -1.f, 1.f);
|
||||
origin += right * deltaTime * MovementSpeed * correctedValue;
|
||||
}
|
||||
|
||||
if (std::abs(LeftStickY) > DEADZONE) {
|
||||
float correctedValue = -remap(LeftStickY, -32767, 32767, -1, 1);
|
||||
origin += forward * deltaTime * MovementSpeed * correctedValue;
|
||||
}
|
||||
|
||||
//Look around Controller
|
||||
float lookMultiplier = 2.f;
|
||||
|
||||
if (std::abs(RightStickX) > DEADZONE) {
|
||||
float correctedValue = remap(RightStickX, -32767.f, 32767.f, -1.f, 1.f);
|
||||
totalYaw += correctedValue * deltaTime * lookMultiplier;
|
||||
rightStickMoved = true;
|
||||
}
|
||||
|
||||
if (std::abs(RightStickY) > DEADZONE) {
|
||||
float correctedValue = -remap(RightStickY, -32767.f, 32767.f, -1.f, 1.f);
|
||||
totalPitch += correctedValue * deltaTime * lookMultiplier;
|
||||
rightStickMoved = true;
|
||||
}
|
||||
|
||||
//Controller Up and Down Triggers
|
||||
|
||||
|
||||
float LeftTrigger = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
|
||||
float RightTrigger = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
|
||||
|
||||
if (std::abs(LeftTrigger) > DEADZONE) {
|
||||
float correctedValue = remap(LeftTrigger, 0.f, 32767.f, 0.f, 1.f);
|
||||
origin -= up * deltaTime * MovementSpeed * correctedValue;
|
||||
}
|
||||
|
||||
if (std::abs(RightTrigger) > DEADZONE) {
|
||||
float correctedValue = remap(RightTrigger, 0.f, 32767.f, 0.f, 1.f);
|
||||
origin += up * deltaTime * MovementSpeed * correctedValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Mouse Input
|
||||
bool mousePosChange{false};
|
||||
int mouseX{}, mouseY{};
|
||||
const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY);
|
||||
mouseY *= -1;
|
||||
|
||||
if (mouseState == SDL_BUTTON_X1) //rmb
|
||||
{
|
||||
totalYaw += (static_cast<float>(mouseX) * mouseSens) * TO_RADIANS;
|
||||
|
||||
totalPitch += (static_cast<float>(mouseY) * mouseSens) * TO_RADIANS;
|
||||
|
||||
mousePosChange = true;
|
||||
} else if (mouseState == SDL_BUTTON_LEFT) {
|
||||
zDirection = forward.Normalized() * static_cast<float>(-mouseY);
|
||||
|
||||
totalYaw += static_cast<float>(mouseX) * mouseSens * TO_RADIANS;
|
||||
|
||||
mousePosChange = true;
|
||||
} else if (mouseState == SDL_BUTTON_X2) //lmb + rmb
|
||||
{
|
||||
origin.y += static_cast<float>(mouseY) / 2;
|
||||
|
||||
mousePosChange = true;
|
||||
}
|
||||
|
||||
origin += ((zDirection + xDirection + yDirection) * cameraSpeed * deltaTime);
|
||||
|
||||
if (mousePosChange || rightStickMoved) {
|
||||
const Matrix yawMatrix{Matrix::CreateRotationY(totalYaw)};
|
||||
const Matrix pitchMatrix{Matrix::CreateRotationX(totalPitch)};
|
||||
|
||||
const Matrix finalRotation{pitchMatrix * yawMatrix};
|
||||
forward = finalRotation.TransformVector(Vector3::UnitZ);
|
||||
forward.Normalize();
|
||||
}
|
||||
|
||||
//Update Matrices
|
||||
CalculateViewMatrix();
|
||||
CalculateProjectionMatrix(); //Try to optimize this - should only be called once or when fov/aspectRatio changes
|
||||
|
||||
}
|
||||
|
||||
dae::Matrix dae::Camera::GetViewProjectionMatrix() const {
|
||||
return viewMatrix * ProjectionMatrix;
|
||||
}
|
||||
57
project/src/Camera.h
Normal file
57
project/src/Camera.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef GP1_DIRECTX_CAMERA_H
|
||||
#define GP1_DIRECTX_CAMERA_H
|
||||
|
||||
#include <cassert>
|
||||
#include <SDL_keyboard.h>
|
||||
#include <SDL_mouse.h>
|
||||
|
||||
#include "Timer.h"
|
||||
#include "Vector3.h"
|
||||
#include "MathHelpers.h"
|
||||
#include "Matrix.h"
|
||||
|
||||
namespace dae {
|
||||
class Camera {
|
||||
public:
|
||||
Camera() = default;
|
||||
|
||||
Camera(const Vector3 &_origin, float _fovAngle);
|
||||
|
||||
void Initialize(float _fovAngle = 90.f, Vector3 _origin = {0.f, 0.f, 0.f}, float _aspect = 1.f);
|
||||
|
||||
void SetFOV(float _fovAngle);
|
||||
|
||||
void CalculateViewMatrix();
|
||||
|
||||
void CalculateProjectionMatrix();
|
||||
|
||||
void Update(const Timer *pTimer);
|
||||
|
||||
Matrix GetViewProjectionMatrix() const;
|
||||
|
||||
private:
|
||||
Vector3 origin{};
|
||||
float fovAngle{90.f};
|
||||
float fov{tanf((fovAngle * TO_RADIANS) / 2.f)};
|
||||
|
||||
Vector3 forward{Vector3::UnitZ};
|
||||
Vector3 up{Vector3::UnitY};
|
||||
Vector3 right{Vector3::UnitX};
|
||||
|
||||
float totalPitch{};
|
||||
float totalYaw{};
|
||||
|
||||
Matrix invViewMatrix{};
|
||||
Matrix viewMatrix{};
|
||||
|
||||
Matrix ProjectionMatrix{};
|
||||
|
||||
float aspect{};
|
||||
float cameraSpeed{4.f};
|
||||
float mouseSens{0.3f};
|
||||
float zNear{.1f};
|
||||
float zFar{100.f};
|
||||
};
|
||||
}
|
||||
|
||||
#endif //GP1_DIRECTX_CAMERA_H
|
||||
124
project/src/ColorRGB.h
Normal file
124
project/src/ColorRGB.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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*=(float s)
|
||||
{
|
||||
r *= s;
|
||||
g *= s;
|
||||
b *= s;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ColorRGB operator/(float s) const
|
||||
{
|
||||
return { r / s, g / s,b / 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 };
|
||||
}
|
||||
}
|
||||
103
project/src/Effect.cpp
Normal file
103
project/src/Effect.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "pch.h"
|
||||
#include "Effect.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
Effect::Effect(ID3D11Device* devicePtr, const std::wstring& filePath)
|
||||
{
|
||||
const std::ifstream file(filePath);
|
||||
if(!file)
|
||||
std::wcout << L"File doesn't exist" << std::endl;
|
||||
|
||||
m_EffectPtr = LoadEffect(devicePtr, filePath);
|
||||
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("PointTechnique");
|
||||
|
||||
if(!m_TechniquePtr->IsValid())
|
||||
std::wcout << L"Technique is not valid" << std::endl;
|
||||
|
||||
m_MatWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gWorldViewProj")->AsMatrix();
|
||||
if(!m_MatWorldViewProjVariablePtr->IsValid())
|
||||
std::wcout << L"gWorldViewProj Matrix is not valid" << std::endl;
|
||||
}
|
||||
|
||||
Effect::~Effect()
|
||||
{
|
||||
m_EffectPtr->Release();
|
||||
m_EffectPtr = nullptr;
|
||||
|
||||
// m_TechniquePtr->Release();
|
||||
// m_TechniquePtr = nullptr;
|
||||
}
|
||||
|
||||
ID3DX11Effect* Effect::LoadEffect(ID3D11Device* devicePtr, const std::wstring& filePath) {
|
||||
HRESULT result;
|
||||
ID3D10Blob *errorBlobPtr{nullptr};
|
||||
ID3DX11Effect *effectPtr;
|
||||
|
||||
DWORD shaderFlags = 0;
|
||||
#if defined( DEBUG ) || defined( _DEBUG )
|
||||
shaderFlags |= D3DCOMPILE_DEBUG;
|
||||
shaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
|
||||
result = D3DX11CompileEffectFromFile(filePath.c_str(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
shaderFlags,
|
||||
0,
|
||||
devicePtr,
|
||||
&effectPtr,
|
||||
&errorBlobPtr);
|
||||
|
||||
if (FAILED(result)) {
|
||||
if (errorBlobPtr != nullptr) {
|
||||
const char *errorsPtr = static_cast<char *>(errorBlobPtr->GetBufferPointer());
|
||||
|
||||
std::wstringstream ss;
|
||||
for (UINT i{}; i < errorBlobPtr->GetBufferSize(); i++)
|
||||
ss << errorsPtr[i];
|
||||
|
||||
OutputDebugStringW(ss.str().c_str());
|
||||
errorBlobPtr->Release();
|
||||
errorBlobPtr = nullptr;
|
||||
|
||||
return nullptr;
|
||||
} else {
|
||||
std::wstringstream ss;
|
||||
ss << "EffectLoader: Failed to CreateEffectFromFile!\nPath: " << filePath;
|
||||
std::wcout << ss.str() << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
std::cout << "Effect loaded" << std::endl;
|
||||
return effectPtr;
|
||||
}
|
||||
|
||||
void Effect::SetWorldViewProjMatrix(const dae::Matrix &matrix) {
|
||||
m_MatWorldViewProjVariablePtr->SetMatrix(reinterpret_cast<const float*>(&matrix));
|
||||
}
|
||||
|
||||
void Effect::SetMaterial(const Material &material) {
|
||||
if(material.diffuseTexturePtr)
|
||||
m_EffectPtr->GetVariableByName("gDiffuseMap")->AsShaderResource()->SetResource(material.diffuseTexturePtr->GetSrv());
|
||||
}
|
||||
|
||||
void Effect::NextTechnique() {
|
||||
switch (m_TechniqueType) {
|
||||
case TechniqueType::Point:
|
||||
m_TechniqueType = TechniqueType::Linear;
|
||||
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("LinearTechnique");
|
||||
std::cout << "Linear" << std::endl;
|
||||
break;
|
||||
case TechniqueType::Linear:
|
||||
m_TechniqueType = TechniqueType::Anisotropic;
|
||||
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("AnisotropicTechnique");
|
||||
std::cout << "Anisotropic" << std::endl;
|
||||
break;
|
||||
case TechniqueType::Anisotropic:
|
||||
m_TechniqueType = TechniqueType::Point;
|
||||
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("PointTechnique");
|
||||
std::cout << "Point" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
36
project/src/Effect.h
Normal file
36
project/src/Effect.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
enum class TechniqueType{
|
||||
Point,
|
||||
Linear,
|
||||
Anisotropic
|
||||
};
|
||||
|
||||
class Effect final
|
||||
{
|
||||
static inline constexpr char TECHNIQUE_NAME[] = "DefaultTechnique";
|
||||
public:
|
||||
Effect(ID3D11Device* devicePtr, const std::wstring& filePath);
|
||||
~Effect();
|
||||
|
||||
inline ID3DX11Effect* GetEffectPtr() const { return m_EffectPtr; }
|
||||
inline ID3DX11EffectTechnique* GetTechniquePtr() const { return m_TechniquePtr; }
|
||||
|
||||
void SetWorldViewProjMatrix(const dae::Matrix &matrix);
|
||||
|
||||
void SetMaterial(const Material &material);
|
||||
|
||||
void NextTechnique();
|
||||
|
||||
private:
|
||||
ID3DX11Effect* m_EffectPtr{ nullptr };
|
||||
ID3DX11EffectTechnique* m_TechniquePtr{};
|
||||
|
||||
static ID3DX11Effect* LoadEffect(ID3D11Device* devicePtr, const std::wstring& filePath);
|
||||
|
||||
ID3DX11EffectMatrixVariable* m_MatWorldViewProjVariablePtr{};
|
||||
|
||||
TechniqueType m_TechniqueType{ TechniqueType::Linear };
|
||||
};
|
||||
55
project/src/GamePadController.cpp
Normal file
55
project/src/GamePadController.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Created by Bram on 11/12/2024.
|
||||
//
|
||||
|
||||
#include "GamePadController.h"
|
||||
|
||||
GamePadController::GamePadController() = default;
|
||||
|
||||
GamePadController::~GamePadController() {
|
||||
for (auto pGameController : m_pGameControllers) {
|
||||
SDL_GameControllerClose(pGameController);
|
||||
}
|
||||
}
|
||||
|
||||
void GamePadController::Init() {
|
||||
const int numJoysticks = SDL_NumJoysticks();
|
||||
for (int i = 0; i < numJoysticks; i++) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
SDL_GameController *pController = SDL_GameControllerOpen(i);
|
||||
if (pController) {
|
||||
m_pGameControllers.push_back(pController);
|
||||
m_GamePads.push_back(GamePad());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GamePadController::Update() {
|
||||
for (int i = 0; i < m_pGameControllers.size(); i++) {
|
||||
SDL_GameController *pController = m_pGameControllers[i];
|
||||
GamePad &gamePad = m_GamePads[i];
|
||||
|
||||
for (int j = 0; j < SDL_CONTROLLER_BUTTON_MAX; j++) {
|
||||
gamePad.buttons[j] = SDL_GameControllerGetButton(pController, (SDL_GameControllerButton) j);
|
||||
}
|
||||
|
||||
for (int j = 0; j < SDL_CONTROLLER_AXIS_MAX; j++) {
|
||||
gamePad.axis[j] = SDL_GameControllerGetAxis(pController, (SDL_GameControllerAxis) j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GamePadController::IsButtonDown(Controllers controller, int button) const {
|
||||
return m_GamePads[controller].buttons[button];
|
||||
}
|
||||
|
||||
bool GamePadController::IsButtonUp(Controllers controller, int button) const {
|
||||
return !m_GamePads[controller].buttons[button];
|
||||
}
|
||||
|
||||
float GamePadController::GetAxis(Controllers controller, int axis) const {
|
||||
return m_GamePads[controller].axis[axis];
|
||||
}
|
||||
|
||||
|
||||
43
project/src/GamePadController.h
Normal file
43
project/src/GamePadController.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef GP1_DIRECTX_GAMEPADCONTROLLER_H
|
||||
#define GP1_DIRECTX_GAMEPADCONTROLLER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "SDL.h"
|
||||
|
||||
|
||||
struct GamePad{
|
||||
bool buttons[SDL_CONTROLLER_BUTTON_MAX];
|
||||
float axis[SDL_CONTROLLER_AXIS_MAX];
|
||||
};
|
||||
|
||||
enum Controllers {PLAYER1, PLAYER2, PLAYER3, PLAYER4};
|
||||
|
||||
class GamePadController {
|
||||
public:
|
||||
|
||||
static GamePadController& GetInstance()
|
||||
{
|
||||
static GamePadController instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
~GamePadController();
|
||||
void Init();
|
||||
void Update();
|
||||
bool IsButtonDown(Controllers controller, int button) const;
|
||||
bool IsButtonUp(Controllers controller, int button) const;
|
||||
|
||||
float GetAxis(Controllers controller, int axis) const;
|
||||
|
||||
bool isAnyControllerConnected() const { return !m_pGameControllers.empty(); }
|
||||
|
||||
private:
|
||||
GamePadController();
|
||||
std::vector<SDL_GameController*> m_pGameControllers;
|
||||
std::vector<GamePad> m_GamePads;
|
||||
};
|
||||
|
||||
|
||||
#endif //GP1_DIRECTX_GAMEPADCONTROLLER_H
|
||||
7
project/src/Math.h
Normal file
7
project/src/Math.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "ColorRGB.h"
|
||||
#include "Vector2.h"
|
||||
#include "Vector3.h"
|
||||
#include "Vector4.h"
|
||||
#include "Matrix.h"
|
||||
#include "MathHelpers.h"
|
||||
57
project/src/MathHelpers.h
Normal file
57
project/src/MathHelpers.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace dae {
|
||||
/* --- HELPER STRUCTS --- */
|
||||
struct Int2 {
|
||||
int x{};
|
||||
int y{};
|
||||
};
|
||||
|
||||
/* --- 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);
|
||||
|
||||
/* --- HELPER FUNCTIONS --- */
|
||||
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 = 0.0001f) {
|
||||
return abs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
inline int Clamp(const int v, int min, int max) {
|
||||
if (v < min) return min;
|
||||
if (v > max) return max;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline float Clamp(const float v, float min, float max) {
|
||||
if (v < min) return min;
|
||||
if (v > max) return max;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline float Saturate(const float v) {
|
||||
|
||||
if (v < 0.f) return 0.f;
|
||||
if (v > 1.f) return 1.f;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline float remap(float value, float low1, float high1, float low2, float high2) {
|
||||
return (value - low1) / (high1 - low1) * (high2 - low2) + low2;
|
||||
}
|
||||
}
|
||||
301
project/src/Matrix.cpp
Normal file
301
project/src/Matrix.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "Matrix.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "MathHelpers.h"
|
||||
#include <cmath>
|
||||
|
||||
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.x, v.y, v.z);
|
||||
}
|
||||
|
||||
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.x, p.y, p.z);
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
Vector4 Matrix::TransformPoint(const Vector4& p) const
|
||||
{
|
||||
return TransformPoint(p.x, p.y, p.z, p.w);
|
||||
}
|
||||
|
||||
Vector4 Matrix::TransformPoint(float x, float y, float z, float w) const
|
||||
{
|
||||
return Vector4{
|
||||
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,
|
||||
data[0].w * x + data[1].w * y + data[2].w * z + data[3].w
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const Matrix& Matrix::Inverse()
|
||||
{
|
||||
//Optimized Inverse as explained in FGED1 - used widely in other libraries too.
|
||||
const Vector3& a = data[0];
|
||||
const Vector3& b = data[1];
|
||||
const Vector3& c = data[2];
|
||||
const Vector3& d = data[3];
|
||||
|
||||
const float x = data[0][3];
|
||||
const float y = data[1][3];
|
||||
const float z = data[2][3];
|
||||
const float w = data[3][3];
|
||||
|
||||
Vector3 s = Vector3::Cross(a, b);
|
||||
Vector3 t = Vector3::Cross(c, d);
|
||||
Vector3 u = a * y - b * x;
|
||||
Vector3 v = c * w - d * z;
|
||||
|
||||
const float det = Vector3::Dot(s, v) + Vector3::Dot(t, u);
|
||||
assert((!AreEqual(det, 0.f)) && "ERROR: determinant is 0, there is no INVERSE!");
|
||||
const float invDet = 1.f / det;
|
||||
|
||||
s *= invDet; t *= invDet; u *= invDet; v *= invDet;
|
||||
|
||||
const Vector3 r0 = Vector3::Cross(b, v) + t * y;
|
||||
const Vector3 r1 = Vector3::Cross(v, a) - t * x;
|
||||
const Vector3 r2 = Vector3::Cross(d, u) + s * w;
|
||||
//Vector3 r3 = Vector3::Cross(u, c) - s * z;
|
||||
|
||||
data[0] = Vector4{ r0.x, r1.x, r2.x, 0.f };
|
||||
data[1] = Vector4{ r0.y, r1.y, r2.y, 0.f };
|
||||
data[2] = Vector4{ r0.z, r1.z, r2.z, 0.f };
|
||||
data[3] = {-Vector3::Dot(b, t),Vector3::Dot(a, t),-Vector3::Dot(d, s),Vector3::Dot(c, s) };
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix Matrix::Transpose(const Matrix& m)
|
||||
{
|
||||
Matrix out{ m };
|
||||
out.Transpose();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Matrix Matrix::Inverse(const Matrix& m)
|
||||
{
|
||||
Matrix out{ m };
|
||||
out.Inverse();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up)
|
||||
{
|
||||
Vector3 zAxis = (forward - origin).Normalized();
|
||||
Vector3 xAxis = Vector3::Cross(up, zAxis).Normalized();
|
||||
Vector3 yAxis = Vector3::Cross(zAxis, xAxis).Normalized();
|
||||
Vector3 trans =
|
||||
{
|
||||
-Vector3::Dot(xAxis, origin),
|
||||
-Vector3::Dot(yAxis, origin),
|
||||
-Vector3::Dot(zAxis, origin)
|
||||
};
|
||||
return {
|
||||
{xAxis.x, yAxis.x, zAxis.x},
|
||||
{xAxis.y, yAxis.y, zAxis.y},
|
||||
{xAxis.z, yAxis.z, zAxis.z},
|
||||
{trans.x, trans.y, trans.z}
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf)
|
||||
{
|
||||
return Matrix(
|
||||
{ 1.f / (aspect * fovy), 0, 0, 0 },
|
||||
{ 0, 1.f / fovy, 0, 0 },
|
||||
{ 0, 0, (zf) / (zf - zn), 1 },
|
||||
{ 0, 0, -(zf * zn) / (zf - zn), 0 }
|
||||
);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return CreateTranslation({ x, y, z });
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateTranslation(const Vector3& t)
|
||||
{
|
||||
return { Vector3::UnitX, Vector3::UnitY, Vector3::UnitZ, t };
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationX(float pitch)
|
||||
{
|
||||
return {
|
||||
{1, 0, 0, 0},
|
||||
{0, cos(pitch), -sin(pitch), 0},
|
||||
{0, sin(pitch), cos(pitch), 0},
|
||||
{0, 0, 0, 1}
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationY(float yaw)
|
||||
{
|
||||
return {
|
||||
{cos(yaw), 0, -sin(yaw), 0},
|
||||
{0, 1, 0, 0},
|
||||
{sin(yaw), 0, cos(yaw), 0},
|
||||
{0, 0, 0, 1}
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationZ(float roll)
|
||||
{
|
||||
return {
|
||||
{cos(roll), sin(roll), 0, 0},
|
||||
{-sin(roll), cos(roll), 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{0, 0, 0, 1}
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotation(float pitch, float yaw, float roll)
|
||||
{
|
||||
return CreateRotation({ pitch, yaw, roll });
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotation(const Vector3& r)
|
||||
{
|
||||
return CreateRotationX(r[0]) * CreateRotationY(r[1]) * CreateRotationZ(r[2]);
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateScale(float sx, float sy, float sz)
|
||||
{
|
||||
return { {sx, 0, 0}, {0, sy, 0}, {0, 0, sz}, Vector3::Zero };
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
75
project/src/Matrix.h
Normal file
75
project/src/Matrix.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#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;
|
||||
|
||||
Vector4 TransformPoint(const Vector4& p) const;
|
||||
Vector4 TransformPoint(float x, float y, float z, float w) const;
|
||||
|
||||
const Matrix& Transpose();
|
||||
const Matrix& Inverse();
|
||||
|
||||
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);
|
||||
static Matrix Inverse(const Matrix& m);
|
||||
|
||||
static Matrix CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up);
|
||||
static Matrix CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf);
|
||||
|
||||
Vector4& operator[](int index);
|
||||
Vector4 operator[](int index) const;
|
||||
Matrix operator*(const Matrix& m) const;
|
||||
const Matrix& operator*=(const Matrix& m);
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
127
project/src/Mesh.cpp
Normal file
127
project/src/Mesh.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#include <cassert>
|
||||
#include "pch.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
#include "Effect.h"
|
||||
|
||||
Mesh::Mesh(ID3D11Device* devicePtr, const std::vector<VertexIn>& verticesIn, const std::vector<Uint32>& indices, const Material& material) :
|
||||
m_EffectPtr(new Effect{ devicePtr, L"resources/PosCol3D.fx" }),
|
||||
m_InputLayoutPtr(nullptr),
|
||||
m_VertexBufferPtr(nullptr),
|
||||
m_IndexBufferPtr(nullptr),
|
||||
m_VerticesIn(verticesIn),
|
||||
m_Indices(indices),
|
||||
m_IndicesCount(static_cast<UINT>(m_Indices.size())),
|
||||
m_Material(material)
|
||||
|
||||
{
|
||||
HRESULT result;
|
||||
D3D11_BUFFER_DESC bufferDesc{};
|
||||
D3D11_SUBRESOURCE_DATA subresourceData{};
|
||||
|
||||
m_EffectPtr->SetMaterial(m_Material);
|
||||
|
||||
//Create vertex layout
|
||||
static constexpr uint32_t vertexElementCount{ 3 };
|
||||
D3D11_INPUT_ELEMENT_DESC vertexDesc[vertexElementCount]{};
|
||||
|
||||
vertexDesc[0].SemanticName = "POSITION";
|
||||
vertexDesc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
vertexDesc[0].AlignedByteOffset = 0;
|
||||
vertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
vertexDesc[1].SemanticName = "COLOR";
|
||||
vertexDesc[1].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, color);
|
||||
|
||||
vertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
vertexDesc[2].SemanticName = "TEXCOORD";
|
||||
vertexDesc[2].Format = DXGI_FORMAT_R32G32_FLOAT;
|
||||
vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, uv);
|
||||
vertexDesc[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
|
||||
|
||||
//Create input layout
|
||||
D3DX11_PASS_DESC passDesc{};
|
||||
ID3DX11EffectTechnique* techniquePtr = m_EffectPtr->GetTechniquePtr();
|
||||
techniquePtr->GetPassByIndex(0)->GetDesc(&passDesc);
|
||||
|
||||
result = devicePtr->CreateInputLayout(
|
||||
vertexDesc,
|
||||
vertexElementCount,
|
||||
passDesc.pIAInputSignature,
|
||||
passDesc.IAInputSignatureSize,
|
||||
&m_InputLayoutPtr);
|
||||
|
||||
assert(result == S_OK && "Creating input layout failed");
|
||||
|
||||
//Create vertex buffer
|
||||
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bufferDesc.ByteWidth = sizeof(verticesIn) * static_cast<uint32_t>(verticesIn.size());
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
subresourceData.pSysMem = verticesIn.data();
|
||||
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_VertexBufferPtr);
|
||||
|
||||
assert(result == S_OK && "Creating vertex buffer failed");
|
||||
|
||||
//Create index buffer
|
||||
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bufferDesc.ByteWidth = sizeof(uint32_t) * m_IndicesCount;
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
subresourceData.pSysMem = m_Indices.data();
|
||||
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_IndexBufferPtr);
|
||||
|
||||
assert(result == S_OK && "Creating index buffer failed");
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
m_InputLayoutPtr->Release();
|
||||
m_InputLayoutPtr = nullptr;
|
||||
|
||||
m_VertexBufferPtr->Release();
|
||||
m_VertexBufferPtr = nullptr;
|
||||
|
||||
m_IndexBufferPtr->Release();
|
||||
m_IndexBufferPtr = nullptr;
|
||||
|
||||
delete m_EffectPtr;
|
||||
m_EffectPtr = nullptr;
|
||||
}
|
||||
|
||||
void Mesh::Render(ID3D11DeviceContext* deviceContextPtr, const Matrix& worldViewProj) const
|
||||
{
|
||||
m_EffectPtr->SetWorldViewProjMatrix(worldViewProj);
|
||||
//1. Set primitive topology
|
||||
deviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
//2. Set input layout
|
||||
deviceContextPtr->IASetInputLayout(m_InputLayoutPtr);
|
||||
|
||||
//3. Set vertex buffer
|
||||
constexpr UINT stride = sizeof(VertexIn);
|
||||
constexpr UINT offset = 0;
|
||||
deviceContextPtr->IASetVertexBuffers(0, 1, &m_VertexBufferPtr, &stride, &offset);
|
||||
|
||||
//4. Set index buffer
|
||||
deviceContextPtr->IASetIndexBuffer(m_IndexBufferPtr, DXGI_FORMAT_R32_UINT, 0);
|
||||
|
||||
//5. Draw
|
||||
D3DX11_TECHNIQUE_DESC techniqueDesc{};
|
||||
m_EffectPtr->GetTechniquePtr()->GetDesc(&techniqueDesc);
|
||||
for (UINT p{}; p < techniqueDesc.Passes; p++)
|
||||
{
|
||||
m_EffectPtr->GetTechniquePtr()->GetPassByIndex(p)->Apply(0, deviceContextPtr);
|
||||
deviceContextPtr->DrawIndexed(m_IndicesCount, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::NextTechnique() {
|
||||
m_EffectPtr->NextTechnique();
|
||||
}
|
||||
63
project/src/Mesh.h
Normal file
63
project/src/Mesh.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "Texture.h"
|
||||
|
||||
class Effect;
|
||||
using namespace dae;
|
||||
|
||||
struct VertexIn;
|
||||
struct VertexOut;
|
||||
|
||||
|
||||
struct Material{
|
||||
Texture* diffuseTexturePtr{ nullptr };
|
||||
|
||||
~Material(){
|
||||
if(diffuseTexturePtr){
|
||||
delete diffuseTexturePtr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Mesh final
|
||||
{
|
||||
public:
|
||||
Mesh(ID3D11Device* devicePtr, const std::vector<VertexIn>& verticesIn, const std::vector<Uint32>& indices, const Material& material);
|
||||
~Mesh();
|
||||
|
||||
void Render(ID3D11DeviceContext* deviceContextPtr, const Matrix& worldViewProj) const;
|
||||
|
||||
void NextTechnique();
|
||||
|
||||
private:
|
||||
Effect* m_EffectPtr;
|
||||
|
||||
ID3D11InputLayout* m_InputLayoutPtr;
|
||||
ID3D11Buffer* m_VertexBufferPtr;
|
||||
ID3D11Buffer* m_IndexBufferPtr;
|
||||
|
||||
std::vector<VertexIn> m_VerticesIn;
|
||||
std::vector<uint32_t> m_Indices;
|
||||
UINT m_IndicesCount;
|
||||
|
||||
Material m_Material{};
|
||||
};
|
||||
|
||||
struct VertexIn
|
||||
{
|
||||
Vector3 position{};
|
||||
Vector3 color{};
|
||||
Vector2 uv{};
|
||||
// Vector3 normal{};
|
||||
// Vector3 tangent{};
|
||||
};
|
||||
|
||||
struct VertexOut
|
||||
{
|
||||
Vector4 position{};
|
||||
Vector3 color{};
|
||||
Vector2 uv{};
|
||||
// Vector3 normal{};
|
||||
|
||||
};
|
||||
|
||||
212
project/src/Renderer.cpp
Normal file
212
project/src/Renderer.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#include "pch.h"
|
||||
#include "Renderer.h"
|
||||
#include "Mesh.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace dae {
|
||||
|
||||
Renderer::Renderer(SDL_Window *pWindow) :
|
||||
m_pWindow(pWindow) {
|
||||
//Initialize
|
||||
SDL_GetWindowSize(pWindow, &m_Width, &m_Height);
|
||||
|
||||
//Initialize DirectX pipeline
|
||||
const HRESULT result = InitializeDirectX();
|
||||
if (result == S_OK) {
|
||||
m_IsInitialized = true;
|
||||
std::cout << "DirectX is initialized and ready!\n";
|
||||
} else {
|
||||
std::cout << "DirectX initialization failed!\n";
|
||||
}
|
||||
std::vector<VertexIn> vertices{};
|
||||
std::vector<uint32_t> indices{};
|
||||
|
||||
if(Utils::ParseOBJ("resources/vehicle.obj", vertices, indices, false)){
|
||||
std::cout << "Model Loaded" << std::endl;
|
||||
} else {
|
||||
std::cout << "Model failed to load" << std::endl;
|
||||
}
|
||||
|
||||
std::vector<VertexIn> quad = {
|
||||
{{-1.f, 1.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 0.f}},
|
||||
{{1.f, 1.f, 0.f}, {0.f, 1.f, 0.f}, {1.f, 0.f}},
|
||||
{{1.f, -1.f, 0.f}, {0.f, 0.f, 1.f}, {1.f, 1.f}},
|
||||
{{-1.f, -1.f, 0.f}, {1.f, 1.f, 1.f}, {0.f, 1.f}}
|
||||
};
|
||||
|
||||
std::vector<uint32_t> quadIndices = {
|
||||
0, 1, 2,
|
||||
0, 2, 3
|
||||
};
|
||||
|
||||
std::cout << "Vertices: " << vertices.size() << " Indices: " << indices.size() << std::endl;
|
||||
|
||||
m_material.diffuseTexturePtr = Texture::LoadFromFile("resources/vehicle_diffuse.png", m_DevicePtr);
|
||||
m_mesh = new Mesh(m_DevicePtr, quad, quadIndices, m_material);
|
||||
|
||||
m_Camera = Camera(Vector3(0.f, 0.f, -5.f), 90.f);
|
||||
m_Camera.Initialize(90.f, Vector3(0.f, 0.f, -5.f), 1.f);
|
||||
}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
m_RenderTargetViewPtr->Release();
|
||||
m_RenderTargetBufferPtr->Release();
|
||||
|
||||
m_DepthStencilViewPtr->Release();
|
||||
m_DepthStencilBufferPtr->Release();
|
||||
|
||||
m_SwapChainPtr->Release();
|
||||
|
||||
if(m_DeviceContextPtr)
|
||||
{
|
||||
m_DeviceContextPtr->ClearState();
|
||||
m_DeviceContextPtr->Flush();
|
||||
m_DeviceContextPtr->Release();
|
||||
}
|
||||
|
||||
m_DevicePtr->Release();
|
||||
|
||||
delete m_mesh;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::Update(const Timer *pTimer) {
|
||||
m_Camera.Update(pTimer);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::Render() const {
|
||||
if (!m_IsInitialized)
|
||||
return;
|
||||
|
||||
//Clear back buffer
|
||||
const float clearColor[] = { .39f, .59f, .93f, 1.f };
|
||||
m_DeviceContextPtr->ClearRenderTargetView(m_RenderTargetViewPtr, clearColor);
|
||||
m_DeviceContextPtr->ClearDepthStencilView(m_DepthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
|
||||
|
||||
Matrix worldViewProj = m_Camera.GetViewProjectionMatrix();
|
||||
Matrix modelMatrix{};
|
||||
|
||||
|
||||
//Render
|
||||
m_mesh->Render(m_DeviceContextPtr, worldViewProj * modelMatrix);
|
||||
|
||||
//Present
|
||||
m_SwapChainPtr->Present(0, 0);
|
||||
|
||||
}
|
||||
|
||||
HRESULT Renderer::InitializeDirectX() {
|
||||
//1. Create device & deviceContext
|
||||
//=====
|
||||
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_1;
|
||||
uint32_t createDeviceFlags = 0;
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, &featureLevel,
|
||||
1, D3D11_SDK_VERSION, &m_DevicePtr, nullptr, &m_DeviceContextPtr);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
//Create DXGI factory
|
||||
IDXGIFactory1* DxgiFactoryPtr{};
|
||||
result = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DxgiFactoryPtr));
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
//2. Create swap chain
|
||||
//=====
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc{};
|
||||
swapChainDesc.BufferDesc.Width = m_Width;
|
||||
swapChainDesc.BufferDesc.Height = m_Height;
|
||||
swapChainDesc.BufferDesc.RefreshRate.Numerator = 1;
|
||||
swapChainDesc.BufferDesc.RefreshRate.Denominator = 60;
|
||||
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 1;
|
||||
swapChainDesc.Windowed = true;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
swapChainDesc.Flags = 0;
|
||||
|
||||
//Get the handle (HWND) from the SDL back buffer
|
||||
SDL_SysWMinfo sysWMInfo{};
|
||||
SDL_GetVersion(&sysWMInfo.version);
|
||||
SDL_GetWindowWMInfo(m_pWindow, &sysWMInfo);
|
||||
swapChainDesc.OutputWindow = sysWMInfo.info.win.window;
|
||||
|
||||
//Create SwapChain
|
||||
result = DxgiFactoryPtr->CreateSwapChain(m_DevicePtr, &swapChainDesc, &m_SwapChainPtr);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
//3. Create depthStencil (DS) & DepthStencilView (DSV)
|
||||
//=====
|
||||
//Resource
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc{};
|
||||
depthStencilDesc.Width = m_Width;
|
||||
depthStencilDesc.Height = m_Height;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.MiscFlags = 0;
|
||||
|
||||
//View
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc{};
|
||||
depthStencilViewDesc.Format = depthStencilDesc.Format;
|
||||
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
depthStencilViewDesc.Texture2D.MipSlice = 0;
|
||||
|
||||
result = m_DevicePtr->CreateTexture2D(&depthStencilDesc, nullptr, &m_DepthStencilBufferPtr);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
result = m_DevicePtr->CreateDepthStencilView(m_DepthStencilBufferPtr, &depthStencilViewDesc, &m_DepthStencilViewPtr);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
//.4 Create RenderTarget (RT) & RenderTargetView (RTV)
|
||||
|
||||
//Resource
|
||||
result = m_SwapChainPtr->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&m_RenderTargetBufferPtr));
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
//View
|
||||
result = m_DevicePtr->CreateRenderTargetView(m_RenderTargetBufferPtr, nullptr, &m_RenderTargetViewPtr);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
|
||||
//5. Bind RTV & DSV to output Merger stage
|
||||
//=====
|
||||
m_DeviceContextPtr->OMSetRenderTargets(1, &m_RenderTargetViewPtr, m_DepthStencilViewPtr);
|
||||
|
||||
//6. Set Viewport
|
||||
//=====
|
||||
D3D11_VIEWPORT viewport{};
|
||||
viewport.Width = static_cast<float>(m_Width);
|
||||
viewport.Height = static_cast<float>(m_Height);
|
||||
viewport.TopLeftX = 0.f;
|
||||
viewport.TopLeftY = 0.f;
|
||||
viewport.MinDepth = 0.f;
|
||||
viewport.MaxDepth = 1.f;
|
||||
m_DeviceContextPtr->RSSetViewports(1, &viewport);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Renderer::SwitchTechnique() {
|
||||
m_mesh->NextTechnique();
|
||||
}
|
||||
}
|
||||
54
project/src/Renderer.h
Normal file
54
project/src/Renderer.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "Mesh.h"
|
||||
#include "Camera.h"
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace dae
|
||||
{
|
||||
class Renderer final
|
||||
{
|
||||
public:
|
||||
Renderer(SDL_Window* pWindow);
|
||||
~Renderer();
|
||||
|
||||
Renderer(const Renderer&) = delete;
|
||||
Renderer(Renderer&&) noexcept = delete;
|
||||
Renderer& operator=(const Renderer&) = delete;
|
||||
Renderer& operator=(Renderer&&) noexcept = delete;
|
||||
|
||||
void Update(const Timer* pTimer);
|
||||
void Render() const;
|
||||
|
||||
//Switching Functions
|
||||
void SwitchTechnique();
|
||||
|
||||
private:
|
||||
SDL_Window* m_pWindow{};
|
||||
|
||||
int m_Width{};
|
||||
int m_Height{};
|
||||
|
||||
bool m_IsInitialized{ false };
|
||||
|
||||
//DIRECTX
|
||||
HRESULT InitializeDirectX();
|
||||
|
||||
ID3D11Device* m_DevicePtr{};
|
||||
ID3D11DeviceContext* m_DeviceContextPtr{};
|
||||
IDXGISwapChain* m_SwapChainPtr{};
|
||||
ID3D11Texture2D* m_DepthStencilBufferPtr{};
|
||||
ID3D11DepthStencilView* m_DepthStencilViewPtr{};
|
||||
ID3D11Resource* m_RenderTargetBufferPtr{};
|
||||
ID3D11RenderTargetView* m_RenderTargetViewPtr{};
|
||||
|
||||
|
||||
Mesh* m_mesh{ nullptr };
|
||||
Material m_material{};
|
||||
|
||||
Camera m_Camera{};
|
||||
|
||||
};
|
||||
}
|
||||
51
project/src/Texture.cpp
Normal file
51
project/src/Texture.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "Texture.h"
|
||||
|
||||
Texture::~Texture() {
|
||||
m_TextureResourceViewPtr->Release();
|
||||
m_TexturePtr->Release();
|
||||
}
|
||||
|
||||
Texture *Texture::LoadFromFile(const std::string &path, ID3D11Device *devicePtr) {
|
||||
SDL_Surface *surface = IMG_Load(path.c_str());
|
||||
if (!surface) {
|
||||
std::cerr << "Failed to load texture: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Texture *texture = new Texture(surface, devicePtr);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
Texture::Texture(SDL_Surface *surfacePtr, ID3D11Device *devicePtr) {
|
||||
DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
D3D11_TEXTURE2D_DESC desc{};
|
||||
desc.Width = surfacePtr->w;
|
||||
desc.Height = surfacePtr->h;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = surfacePtr->pixels;
|
||||
initData.SysMemPitch = static_cast<UINT>(surfacePtr->pitch);
|
||||
initData.SysMemSlicePitch = static_cast<UINT>(surfacePtr->h * surfacePtr->pitch);
|
||||
|
||||
HRESULT hr = devicePtr->CreateTexture2D(&desc, &initData, &m_TexturePtr);
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc{};
|
||||
SRVDesc.Format = format;
|
||||
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
SRVDesc.Texture2D.MipLevels = 1;
|
||||
|
||||
hr = devicePtr->CreateShaderResourceView(m_TexturePtr, &SRVDesc, &m_TextureResourceViewPtr);
|
||||
|
||||
SDL_FreeSurface(surfacePtr);
|
||||
|
||||
}
|
||||
28
project/src/Texture.h
Normal file
28
project/src/Texture.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef GP1_DIRECTX_TEXTURE_H
|
||||
#define GP1_DIRECTX_TEXTURE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <d3d11.h>
|
||||
#include "Texture.h"
|
||||
#include "SDL_surface.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
~Texture();
|
||||
|
||||
static Texture* LoadFromFile(const std::string& path, ID3D11Device* devicePtr);
|
||||
|
||||
inline ID3D11ShaderResourceView* GetSrv() const { return m_TextureResourceViewPtr; }
|
||||
|
||||
private:
|
||||
Texture(SDL_Surface* surfacePtr, ID3D11Device* devicePtr);
|
||||
|
||||
ID3D11ShaderResourceView* m_TextureResourceViewPtr{};
|
||||
ID3D11Texture2D* m_TexturePtr{};
|
||||
};
|
||||
|
||||
|
||||
#endif //GP1_DIRECTX_TEXTURE_H
|
||||
86
project/src/Timer.cpp
Normal file
86
project/src/Timer.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "pch.h"
|
||||
#include "Timer.h"
|
||||
|
||||
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::Update()
|
||||
{
|
||||
if (m_IsStopped)
|
||||
{
|
||||
m_FPS = 0;
|
||||
m_ElapsedTime = 0.0f;
|
||||
m_TotalTime = static_cast<float>(((m_StopTime - m_PausedTime) - m_BaseTime) * m_BaseTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t currentTime = SDL_GetPerformanceCounter();
|
||||
m_CurrentTime = currentTime;
|
||||
|
||||
m_ElapsedTime = static_cast<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 = static_cast<float>(m_CurrentTime - m_PausedTime - m_BaseTime) * m_SecondsPerCount;
|
||||
|
||||
//FPS LOGIC
|
||||
m_FPSTimer += m_ElapsedTime;
|
||||
++m_FPSCount;
|
||||
if (m_FPSTimer >= 1.0f)
|
||||
{
|
||||
m_dFPS = static_cast<float>(m_FPSCount) / m_FPSTimer;
|
||||
m_FPS = m_FPSCount;
|
||||
m_FPSCount = 0;
|
||||
m_FPSTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::Stop()
|
||||
{
|
||||
if (!m_IsStopped)
|
||||
{
|
||||
const uint64_t currentTime = SDL_GetPerformanceCounter();
|
||||
|
||||
m_StopTime = currentTime;
|
||||
m_IsStopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
project/src/Timer.h
Normal file
50
project/src/Timer.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
//Standard includes
|
||||
#include <cstdint>
|
||||
|
||||
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 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;
|
||||
};
|
||||
}
|
||||
9
project/src/Utils.cpp
Normal file
9
project/src/Utils.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "Math.h"
|
||||
#include "Mesh.h"
|
||||
145
project/src/Utils.h
Normal file
145
project/src/Utils.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "Math.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
namespace dae
|
||||
{
|
||||
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<VertexIn>& vertices, std::vector<uint32_t>& indices, bool flipAxisAndWinding = true) {
|
||||
std::ifstream file(filename);
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
std::vector<Vector3> positions{};
|
||||
std::vector<Vector3> normals{};
|
||||
std::vector<Vector2> UVs{};
|
||||
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
|
||||
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.emplace_back(x, y, z);
|
||||
} else if (sCommand == "vt") {
|
||||
// Vertex TexCoord
|
||||
float u, v;
|
||||
file >> u >> v;
|
||||
UVs.emplace_back(u, 1 - v);
|
||||
} else if (sCommand == "vn") {
|
||||
// Vertex Normal
|
||||
float x, y, z;
|
||||
file >> x >> y >> z;
|
||||
|
||||
normals.emplace_back(x, y, z);
|
||||
} else if (sCommand == "f") {
|
||||
//if a face is read:
|
||||
//construct the 3 vertices, add them to the vertex array
|
||||
//add three indices to the index array
|
||||
//add the material index as attibute to the attribute array
|
||||
//
|
||||
// Faces or triangles
|
||||
VertexIn vertex{};
|
||||
size_t iPosition, iTexCoord, iNormal;
|
||||
|
||||
uint32_t tempIndices[3];
|
||||
for (size_t iFace = 0; iFace < 3; iFace++) {
|
||||
// OBJ format uses 1-based arrays
|
||||
file >> iPosition;
|
||||
vertex.position = positions[iPosition - 1].ToVector4();
|
||||
|
||||
if ('/' == file.peek())//is next in buffer == '/' ?
|
||||
{
|
||||
file.ignore();//read and ignore one element ('/')
|
||||
|
||||
if ('/' != file.peek()) {
|
||||
// Optional texture coordinate
|
||||
file >> iTexCoord;
|
||||
vertex.uv = UVs[iTexCoord - 1];
|
||||
}
|
||||
|
||||
if ('/' == file.peek()) {
|
||||
file.ignore();
|
||||
|
||||
// Optional vertex normal
|
||||
file >> iNormal;
|
||||
// vertex.normal = normals[iNormal - 1];
|
||||
}
|
||||
}
|
||||
|
||||
vertices.push_back(vertex);
|
||||
tempIndices[iFace] = uint32_t(vertices.size()) - 1;
|
||||
//indices.push_back(uint32_t(vertices.size()) - 1);
|
||||
}
|
||||
|
||||
indices.push_back(tempIndices[0]);
|
||||
if (flipAxisAndWinding) {
|
||||
indices.push_back(tempIndices[2]);
|
||||
indices.push_back(tempIndices[1]);
|
||||
} else {
|
||||
indices.push_back(tempIndices[1]);
|
||||
indices.push_back(tempIndices[2]);
|
||||
}
|
||||
}
|
||||
//read till end of line and ignore all remaining chars
|
||||
file.ignore(1000, '\n');
|
||||
}
|
||||
|
||||
// //Cheap Tangent Calculations
|
||||
// for (uint32_t i = 0; i < indices.size(); i += 3) {
|
||||
// uint32_t index0 = indices[i];
|
||||
// uint32_t index1 = indices[size_t(i) + 1];
|
||||
// uint32_t index2 = indices[size_t(i) + 2];
|
||||
//
|
||||
// const Vector3 &p0 = vertices[index0].position;
|
||||
// const Vector3 &p1 = vertices[index1].position;
|
||||
// const Vector3 &p2 = vertices[index2].position;
|
||||
// const Vector2 &uv0 = vertices[index0].uv;
|
||||
// const Vector2 &uv1 = vertices[index1].uv;
|
||||
// const Vector2 &uv2 = vertices[index2].uv;
|
||||
//
|
||||
// const Vector3 edge0 = p1 - p0;
|
||||
// const Vector3 edge1 = p2 - p0;
|
||||
// const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x);
|
||||
// const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y);
|
||||
// float r = 1.f / Vector2::Cross(diffX, diffY);
|
||||
//
|
||||
// Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r;
|
||||
// vertices[index0].tangent += tangent;
|
||||
// vertices[index1].tangent += tangent;
|
||||
// vertices[index2].tangent += tangent;
|
||||
// }
|
||||
//
|
||||
// //Fix the tangents per vertex now because we accumulated
|
||||
// for (auto &v: vertices) {
|
||||
// v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized();
|
||||
//
|
||||
// if (flipAxisAndWinding) {
|
||||
// v.position.z *= -1.f;
|
||||
// v.normal.z *= -1.f;
|
||||
// v.tangent.z *= -1.f;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
}
|
||||
}
|
||||
117
project/src/Vector2.cpp
Normal file
117
project/src/Vector2.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "Vector2.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace dae {
|
||||
const Vector2 Vector2::UnitX = Vector2{ 1, 0 };
|
||||
const Vector2 Vector2::UnitY = Vector2{ 0, 1 };
|
||||
const Vector2 Vector2::Zero = Vector2{ 0, 0 };
|
||||
|
||||
Vector2::Vector2(float _x, float _y) : x(_x), y(_y) {}
|
||||
|
||||
|
||||
Vector2::Vector2(const Vector2& from, const Vector2& to) : x(to.x - from.x), y(to.y - from.y) {}
|
||||
|
||||
float Vector2::Magnitude() const
|
||||
{
|
||||
return sqrtf(x * x + y * y);
|
||||
}
|
||||
|
||||
float Vector2::SqrMagnitude() const
|
||||
{
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
float Vector2::Normalize()
|
||||
{
|
||||
const float m = Magnitude();
|
||||
x /= m;
|
||||
y /= m;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
Vector2 Vector2::Normalized() const
|
||||
{
|
||||
const float m = Magnitude();
|
||||
return { x / m, y / m};
|
||||
}
|
||||
|
||||
float Vector2::Dot(const Vector2& v1, const Vector2& v2)
|
||||
{
|
||||
return v1.x * v2.x + v1.y * v2.y;
|
||||
}
|
||||
|
||||
float Vector2::Cross(const Vector2& v1, const Vector2& v2)
|
||||
{
|
||||
return v1.x * v2.y - v1.y * v2.x;
|
||||
}
|
||||
|
||||
#pragma region Operator Overloads
|
||||
Vector2 Vector2::operator*(float scale) const
|
||||
{
|
||||
return { x * scale, y * scale };
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator/(float scale) const
|
||||
{
|
||||
return { x / scale, y / scale };
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator+(const Vector2& v) const
|
||||
{
|
||||
return { x + v.x, y + v.y };
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator-(const Vector2& v) const
|
||||
{
|
||||
return { x - v.x, y - v.y };
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator-() const
|
||||
{
|
||||
return { -x ,-y };
|
||||
}
|
||||
|
||||
Vector2& Vector2::operator*=(float scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2& Vector2::operator/=(float scale)
|
||||
{
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2& Vector2::operator-=(const Vector2& v)
|
||||
{
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2& Vector2::operator+=(const Vector2& v)
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float& Vector2::operator[](int index)
|
||||
{
|
||||
assert(index <= 1 && index >= 0);
|
||||
return index == 0 ? x : y;
|
||||
}
|
||||
|
||||
float Vector2::operator[](int index) const
|
||||
{
|
||||
assert(index <= 1 && index >= 0);
|
||||
return index == 0 ? x : y;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
46
project/src/Vector2.h
Normal file
46
project/src/Vector2.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct Vector2
|
||||
{
|
||||
float x{};
|
||||
float y{};
|
||||
|
||||
Vector2() = default;
|
||||
Vector2(float _x, float _y);
|
||||
Vector2(const Vector2& from, const Vector2& to);
|
||||
|
||||
float Magnitude() const;
|
||||
float SqrMagnitude() const;
|
||||
float Normalize();
|
||||
Vector2 Normalized() const;
|
||||
|
||||
static float Dot(const Vector2& v1, const Vector2& v2);
|
||||
static float Cross(const Vector2& v1, const Vector2& v2);
|
||||
|
||||
//Member Operators
|
||||
Vector2 operator*(float scale) const;
|
||||
Vector2 operator/(float scale) const;
|
||||
Vector2 operator+(const Vector2& v) const;
|
||||
Vector2 operator-(const Vector2& v) const;
|
||||
Vector2 operator-() const;
|
||||
//Vector2& operator-();
|
||||
Vector2& operator+=(const Vector2& v);
|
||||
Vector2& operator-=(const Vector2& v);
|
||||
Vector2& operator/=(float scale);
|
||||
Vector2& operator*=(float scale);
|
||||
float& operator[](int index);
|
||||
float operator[](int index) const;
|
||||
|
||||
static const Vector2 UnitX;
|
||||
static const Vector2 UnitY;
|
||||
static const Vector2 Zero;
|
||||
};
|
||||
|
||||
//Global Operators
|
||||
inline Vector2 operator*(float scale, const Vector2& v)
|
||||
{
|
||||
return { v.x * scale, v.y * scale };
|
||||
}
|
||||
}
|
||||
168
project/src/Vector3.cpp
Normal file
168
project/src/Vector3.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "Vector3.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "Vector4.h"
|
||||
#include "Vector2.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 sqrtf(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)
|
||||
{
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
return Vector3{
|
||||
v1.y * v2.z - v1.z * v2.y,
|
||||
v1.z * v2.x - v1.x * v2.z,
|
||||
v1.x * v2.y - v1.y * v2.x
|
||||
};
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
Vector2 Vector3::GetXY() const
|
||||
{
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
59
project/src/Vector3.h
Normal file
59
project/src/Vector3.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct Vector2;
|
||||
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);
|
||||
|
||||
Vector4 ToPoint4() const;
|
||||
Vector4 ToVector4() const;
|
||||
|
||||
Vector2 GetXY() 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;
|
||||
|
||||
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 };
|
||||
}
|
||||
}
|
||||
102
project/src/Vector4.cpp
Normal file
102
project/src/Vector4.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "Vector4.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "Vector2.h"
|
||||
#include "Vector3.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 sqrtf(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 };
|
||||
}
|
||||
|
||||
Vector2 Vector4::GetXY() const
|
||||
{
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
Vector3 Vector4::GetXYZ() const
|
||||
{
|
||||
return { x,y,z };
|
||||
}
|
||||
|
||||
float Vector4::Dot(const Vector4& v1, const Vector4& v2)
|
||||
{
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
36
project/src/Vector4.h
Normal file
36
project/src/Vector4.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
namespace dae
|
||||
{
|
||||
struct Vector2;
|
||||
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;
|
||||
|
||||
Vector2 GetXY() const;
|
||||
Vector3 GetXYZ() 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;
|
||||
};
|
||||
}
|
||||
110
project/src/main.cpp
Normal file
110
project/src/main.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "pch.h"
|
||||
|
||||
#if defined(_DEBUG)
|
||||
|
||||
#include "vld.h"
|
||||
|
||||
#endif
|
||||
|
||||
#undef main
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "GamePadController.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 | SDL_INIT_JOYSTICK);
|
||||
|
||||
const uint32_t width = 640;
|
||||
const uint32_t height = 480;
|
||||
|
||||
SDL_Window *pWindow = SDL_CreateWindow(
|
||||
"DirectX - Bram Verhulst - 2GD11E",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width, height, 0);
|
||||
|
||||
if (!pWindow)
|
||||
return 1;
|
||||
|
||||
|
||||
int joysticks = SDL_NumJoysticks();
|
||||
std::cout << "Number of joysticks connected: " << joysticks << std::endl;
|
||||
|
||||
// If there are joysticks connected, open one up for reading
|
||||
if (joysticks > 0) {
|
||||
if (SDL_JoystickOpen(0) == NULL) {
|
||||
std::cerr << "Failed to open joystick 0" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
std::cout << "No joysticks connected" << std::endl;
|
||||
}
|
||||
|
||||
GamePadController::GetInstance().Init();
|
||||
|
||||
|
||||
//Initialize "framework"
|
||||
const auto pTimer = new Timer();
|
||||
const auto pRenderer = new Renderer(pWindow);
|
||||
|
||||
//Start loop
|
||||
pTimer->Start();
|
||||
float printTimer = 0.f;
|
||||
bool isLooping = true;
|
||||
while (isLooping) {
|
||||
//--------- Get input events ---------
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e)) {
|
||||
switch (e.type) {
|
||||
case SDL_QUIT:
|
||||
isLooping = false;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
//Test for a key
|
||||
//if (e.key.keysym.scancode == SDL_SCANCODE_X)
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F2) {
|
||||
pRenderer->SwitchTechnique();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GamePadController::GetInstance().Update();
|
||||
//--------- Update ---------
|
||||
pRenderer->Update(pTimer);
|
||||
|
||||
//--------- Render ---------
|
||||
pRenderer->Render();
|
||||
|
||||
//--------- Timer ---------
|
||||
pTimer->Update();
|
||||
printTimer += pTimer->GetElapsed();
|
||||
if (printTimer >= 1.f) {
|
||||
printTimer = 0.f;
|
||||
std::cout << "dFPS: " << pTimer->GetdFPS() << std::endl;
|
||||
}
|
||||
}
|
||||
pTimer->Stop();
|
||||
|
||||
//Shutdown "framework"
|
||||
delete pRenderer;
|
||||
delete pTimer;
|
||||
|
||||
ShutDown(pWindow);
|
||||
return 0;
|
||||
}
|
||||
1
project/src/pch.cpp
Normal file
1
project/src/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
||||
24
project/src/pch.h
Normal file
24
project/src/pch.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#define NOMINMAX //for directx
|
||||
|
||||
// SDL Headers
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_surface.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
// DirectX Headers
|
||||
#include <dxgi.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <d3dx11effect.h>
|
||||
|
||||
// Framework Headers
|
||||
#include "Timer.h"
|
||||
#include "Math.h"
|
||||
Reference in New Issue
Block a user