From 77e7f8adb11674b4f0571e0ae00ca306b6e1fd39 Mon Sep 17 00:00:00 2001 From: bobnone Date: Wed, 18 May 2022 08:39:22 -0500 Subject: [PATCH 1/6] Finished 4.1 --- Chapter01/Game.vcxproj | 6 +- Chapter02/Game.vcxproj | 6 +- Chapter03/Game.vcxproj | 6 +- Chapter04/AIComponent.cpp | 28 +++--- Chapter04/AIComponent.h | 9 +- Chapter04/AIState.cpp | 7 +- Chapter04/AIState.h | 36 +++----- Chapter04/Actor.cpp | 23 ++--- Chapter04/Actor.h | 16 +--- Chapter04/Bullet.cpp | 18 ++-- Chapter04/Bullet.h | 6 +- Chapter04/CircleComponent.cpp | 13 +-- Chapter04/CircleComponent.h | 4 +- Chapter04/Component.cpp | 10 +-- Chapter04/Component.h | 5 +- Chapter04/Enemy.cpp | 22 ++--- Chapter04/Enemy.h | 10 ++- Chapter04/Game.cpp | 69 +++++---------- Chapter04/Game.h | 19 ++-- Chapter04/Game.vcxproj | 6 +- Chapter04/Grid.cpp | 61 +++++-------- Chapter04/Grid.h | 16 +--- Chapter04/Main.cpp | 2 +- Chapter04/Math.cpp | 46 +++------- Chapter04/Math.h | 160 ++-------------------------------- Chapter04/MoveComponent.cpp | 19 ++-- Chapter04/MoveComponent.h | 5 +- Chapter04/NavComponent.cpp | 24 +++-- Chapter04/NavComponent.h | 6 +- Chapter04/Search.cpp | 97 +++++++-------------- Chapter04/SpriteComponent.cpp | 34 +++----- Chapter04/SpriteComponent.h | 8 +- Chapter04/Tile.cpp | 17 +--- Chapter04/Tile.h | 15 ++-- Chapter04/Tower.cpp | 22 +++-- Chapter04/Tower.h | 8 +- Chapter05/Game.vcxproj | 6 +- TODO.txt | 35 ++++++++ 38 files changed, 296 insertions(+), 604 deletions(-) create mode 100644 TODO.txt diff --git a/Chapter01/Game.vcxproj b/Chapter01/Game.vcxproj index e16204f8..2e8700f9 100644 --- a/Chapter01/Game.vcxproj +++ b/Chapter01/Game.vcxproj @@ -21,19 +21,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode diff --git a/Chapter02/Game.vcxproj b/Chapter02/Game.vcxproj index 35c39009..6f1935a5 100644 --- a/Chapter02/Game.vcxproj +++ b/Chapter02/Game.vcxproj @@ -35,19 +35,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode diff --git a/Chapter03/Game.vcxproj b/Chapter03/Game.vcxproj index fd6197c8..d3e4460d 100644 --- a/Chapter03/Game.vcxproj +++ b/Chapter03/Game.vcxproj @@ -43,19 +43,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode diff --git a/Chapter04/AIComponent.cpp b/Chapter04/AIComponent.cpp index e88ac6ab..d3c8e38e 100644 --- a/Chapter04/AIComponent.cpp +++ b/Chapter04/AIComponent.cpp @@ -11,44 +11,46 @@ #include "AIState.h" #include -AIComponent::AIComponent(class Actor* owner) -:Component(owner) -,mCurrentState(nullptr) +AIComponent::AIComponent(class Actor* owner): Component(owner), pCurrentState(nullptr) { } void AIComponent::Update(float deltaTime) { - if (mCurrentState) + if (pCurrentState) { - mCurrentState->Update(deltaTime); + pCurrentState->Update(deltaTime); } } void AIComponent::ChangeState(const std::string& name) { - // First exit the current state - if (mCurrentState) + if (pCurrentState) { - mCurrentState->OnExit(); + // Check if we even need to change states + if (pCurrentState->GetName() == name) + { + return; + } + // First exit the current state + pCurrentState->OnExit(); } - // Try to find the new state from the map auto iter = mStateMap.find(name); if (iter != mStateMap.end()) { - mCurrentState = iter->second; + pCurrentState = iter->second; // We're entering the new state - mCurrentState->OnEnter(); + pCurrentState->OnEnter(); } else { SDL_Log("Could not find AIState %s in state map", name.c_str()); - mCurrentState = nullptr; + pCurrentState = nullptr; } } void AIComponent::RegisterState(AIState* state) { mStateMap.emplace(state->GetName(), state); -} +} \ No newline at end of file diff --git a/Chapter04/AIComponent.h b/Chapter04/AIComponent.h index 932de9a1..ffa99960 100644 --- a/Chapter04/AIComponent.h +++ b/Chapter04/AIComponent.h @@ -11,19 +11,18 @@ #include #include -class AIComponent : public Component +class AIComponent: public Component { public: AIComponent(class Actor* owner); - void Update(float deltaTime) override; void ChangeState(const std::string& name); - // Add a new state to the map void RegisterState(class AIState* state); + class AIState* GetState() { return pCurrentState; } private: // Maps name of state to AIState instance std::unordered_map mStateMap; // Current state we're in - class AIState* mCurrentState; -}; + class AIState* pCurrentState; +}; \ No newline at end of file diff --git a/Chapter04/AIState.cpp b/Chapter04/AIState.cpp index 673e9b42..4ba03e95 100644 --- a/Chapter04/AIState.cpp +++ b/Chapter04/AIState.cpp @@ -13,11 +13,6 @@ void AIPatrol::Update(float deltaTime) { SDL_Log("Updating %s state", GetName()); - bool dead = true; - if (dead) - { - mOwner->ChangeState("Death"); - } } void AIPatrol::OnEnter() @@ -58,4 +53,4 @@ void AIAttack::OnEnter() void AIAttack::OnExit() { SDL_Log("Exiting %s state", GetName()); -} +} \ No newline at end of file diff --git a/Chapter04/AIState.h b/Chapter04/AIState.h index 67ef2fd1..1fa31000 100644 --- a/Chapter04/AIState.h +++ b/Chapter04/AIState.h @@ -11,9 +11,8 @@ class AIState { public: - AIState(class AIComponent* owner) - :mOwner(owner) - { } + AIState(class AIComponent* owner): pOwner(owner) + {} // State-specific behavior virtual void Update(float deltaTime) = 0; virtual void OnEnter() = 0; @@ -21,51 +20,42 @@ class AIState // Getter for string name of state virtual const char* GetName() const = 0; protected: - class AIComponent* mOwner; + class AIComponent* pOwner; }; -class AIPatrol : public AIState +class AIPatrol: public AIState { public: - AIPatrol(class AIComponent* owner) - :AIState(owner) - { } - + AIPatrol(class AIComponent* owner): AIState(owner) + {} // Override with behaviors for this state void Update(float deltaTime) override; void OnEnter() override; void OnExit() override; - const char* GetName() const override { return "Patrol"; } }; -class AIDeath : public AIState +class AIDeath: public AIState { public: - AIDeath(class AIComponent* owner) - :AIState(owner) - { } - + AIDeath(class AIComponent* owner): AIState(owner) + {} void Update(float deltaTime) override; void OnEnter() override; void OnExit() override; - const char* GetName() const override { return "Death"; } }; -class AIAttack : public AIState +class AIAttack: public AIState { public: - AIAttack(class AIComponent* owner) - :AIState(owner) - { } - + AIAttack(class AIComponent* owner): AIState(owner) + {} void Update(float deltaTime) override; void OnEnter() override; void OnExit() override; - const char* GetName() const override { return "Attack"; } -}; +}; \ No newline at end of file diff --git a/Chapter04/Actor.cpp b/Chapter04/Actor.cpp index 4b8eea91..5c2fb345 100644 --- a/Chapter04/Actor.cpp +++ b/Chapter04/Actor.cpp @@ -11,19 +11,14 @@ #include "Component.h" #include -Actor::Actor(Game* game) - :mState(EActive) - , mPosition(Vector2::Zero) - , mScale(1.0f) - , mRotation(0.0f) - , mGame(game) +Actor::Actor(Game* game): mState(EActive), mPosition(Vector2::Zero), mScale(1.0f), mRotation(0.0f), pGame(game) { - mGame->AddActor(this); + pGame->AddActor(this); } Actor::~Actor() { - mGame->RemoveActor(this); + pGame->RemoveActor(this); // Need to delete components // Because ~Component calls RemoveComponent, need a different style loop while (!mComponents.empty()) @@ -43,7 +38,7 @@ void Actor::Update(float deltaTime) void Actor::UpdateComponents(float deltaTime) { - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->Update(deltaTime); } @@ -58,11 +53,10 @@ void Actor::ProcessInput(const uint8_t* keyState) if (mState == EActive) { // First process input for components - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->ProcessInput(keyState); } - ActorInput(keyState); } } @@ -77,16 +71,13 @@ void Actor::AddComponent(Component* component) // (The first element with a order higher than me) int myOrder = component->GetUpdateOrder(); auto iter = mComponents.begin(); - for (; - iter != mComponents.end(); - ++iter) + for (; iter != mComponents.end(); ++iter) { if (myOrder < (*iter)->GetUpdateOrder()) { break; } } - // Inserts element before position of iterator mComponents.insert(iter, component); } @@ -98,4 +89,4 @@ void Actor::RemoveComponent(Component* component) { mComponents.erase(iter); } -} +} \ No newline at end of file diff --git a/Chapter04/Actor.h b/Chapter04/Actor.h index 767d3c1a..c5902ec3 100644 --- a/Chapter04/Actor.h +++ b/Chapter04/Actor.h @@ -23,19 +23,16 @@ class Actor Actor(class Game* game); virtual ~Actor(); - // Update function called from Game (not overridable) void Update(float deltaTime); // Updates all the components attached to the actor (not overridable) void UpdateComponents(float deltaTime); // Any actor-specific update code (overridable) virtual void UpdateActor(float deltaTime); - // ProcessInput function called from Game (not overridable) void ProcessInput(const uint8_t* keyState); // Any actor-specific input code (overridable) virtual void ActorInput(const uint8_t* keyState); - // Getters/setters const Vector2& GetPosition() const { return mPosition; } void SetPosition(const Vector2& pos) { mPosition = pos; } @@ -43,27 +40,20 @@ class Actor void SetScale(float scale) { mScale = scale; } float GetRotation() const { return mRotation; } void SetRotation(float rotation) { mRotation = rotation; } - Vector2 GetForward() const { return Vector2(Math::Cos(mRotation), -Math::Sin(mRotation)); } - State GetState() const { return mState; } void SetState(State state) { mState = state; } - - class Game* GetGame() { return mGame; } - - + class Game* GetGame() { return pGame; } // Add/remove components void AddComponent(class Component* component); void RemoveComponent(class Component* component); private: // Actor's state State mState; - // Transform Vector2 mPosition; float mScale; float mRotation; - std::vector mComponents; - class Game* mGame; -}; + class Game* pGame; +}; \ No newline at end of file diff --git a/Chapter04/Bullet.cpp b/Chapter04/Bullet.cpp index fddb6949..2b976b2b 100644 --- a/Chapter04/Bullet.cpp +++ b/Chapter04/Bullet.cpp @@ -13,29 +13,24 @@ #include "Game.h" #include "Enemy.h" -Bullet::Bullet(class Game* game) -:Actor(game) +Bullet::Bullet(class Game* game): Actor(game) { SpriteComponent* sc = new SpriteComponent(this); sc->SetTexture(game->GetTexture("Assets/Projectile.png")); - MoveComponent* mc = new MoveComponent(this); mc->SetForwardSpeed(400.0f); - - mCircle = new CircleComponent(this); - mCircle->SetRadius(5.0f); - + pCircle = new CircleComponent(this); + pCircle->SetRadius(5.0f); mLiveTime = 1.0f; } void Bullet::UpdateActor(float deltaTime) { Actor::UpdateActor(deltaTime); - // Check for collision vs enemies - for (Enemy* e : GetGame()->GetEnemies()) + for (Enemy* e: GetGame()->GetEnemies()) { - if (Intersect(*mCircle, *(e->GetCircle()))) + if (Intersect(*pCircle, *(e->GetCircle()))) { // We both die on collision e->SetState(EDead); @@ -43,11 +38,10 @@ void Bullet::UpdateActor(float deltaTime) break; } } - mLiveTime -= deltaTime; if (mLiveTime <= 0.0f) { // Time limit hit, die SetState(EDead); } -} +} \ No newline at end of file diff --git a/Chapter04/Bullet.h b/Chapter04/Bullet.h index 2c1690c4..8d033a88 100644 --- a/Chapter04/Bullet.h +++ b/Chapter04/Bullet.h @@ -9,12 +9,12 @@ #pragma once #include "Actor.h" -class Bullet : public Actor +class Bullet: public Actor { public: Bullet(class Game* game); void UpdateActor(float deltaTime) override; private: - class CircleComponent* mCircle; + class CircleComponent* pCircle; float mLiveTime; -}; +}; \ No newline at end of file diff --git a/Chapter04/CircleComponent.cpp b/Chapter04/CircleComponent.cpp index d41aab2c..e0e31b71 100644 --- a/Chapter04/CircleComponent.cpp +++ b/Chapter04/CircleComponent.cpp @@ -9,21 +9,18 @@ #include "CircleComponent.h" #include "Actor.h" -CircleComponent::CircleComponent(class Actor* owner) -:Component(owner) -,mRadius(0.0f) +CircleComponent::CircleComponent(class Actor* owner): Component(owner), mRadius(0.0f) { - } const Vector2& CircleComponent::GetCenter() const { - return mOwner->GetPosition(); + return pOwner->GetPosition(); } float CircleComponent::GetRadius() const { - return mOwner->GetScale() * mRadius; + return pOwner->GetScale() * mRadius; } bool Intersect(const CircleComponent& a, const CircleComponent& b) @@ -31,10 +28,8 @@ bool Intersect(const CircleComponent& a, const CircleComponent& b) // Calculate distance squared Vector2 diff = a.GetCenter() - b.GetCenter(); float distSq = diff.LengthSq(); - // Calculate sum of radii squared float radiiSq = a.GetRadius() + b.GetRadius(); radiiSq *= radiiSq; - return distSq <= radiiSq; -} +} \ No newline at end of file diff --git a/Chapter04/CircleComponent.h b/Chapter04/CircleComponent.h index 4eecb2a4..d9ef1864 100644 --- a/Chapter04/CircleComponent.h +++ b/Chapter04/CircleComponent.h @@ -14,13 +14,11 @@ class CircleComponent : public Component { public: CircleComponent(class Actor* owner); - void SetRadius(float radius) { mRadius = radius; } float GetRadius() const; - const Vector2& GetCenter() const; private: float mRadius; }; -bool Intersect(const CircleComponent& a, const CircleComponent& b); +bool Intersect(const CircleComponent& a, const CircleComponent& b); \ No newline at end of file diff --git a/Chapter04/Component.cpp b/Chapter04/Component.cpp index c4ed432d..5446d684 100644 --- a/Chapter04/Component.cpp +++ b/Chapter04/Component.cpp @@ -9,19 +9,17 @@ #include "Component.h" #include "Actor.h" -Component::Component(Actor* owner, int updateOrder) - :mOwner(owner) - ,mUpdateOrder(updateOrder) +Component::Component(Actor* owner, int updateOrder): pOwner(owner), mUpdateOrder(updateOrder) { // Add to actor's vector of components - mOwner->AddComponent(this); + pOwner->AddComponent(this); } Component::~Component() { - mOwner->RemoveComponent(this); + pOwner->RemoveComponent(this); } void Component::Update(float deltaTime) { -} +} \ No newline at end of file diff --git a/Chapter04/Component.h b/Chapter04/Component.h index fb41dd75..870d895e 100644 --- a/Chapter04/Component.h +++ b/Chapter04/Component.h @@ -21,11 +21,10 @@ class Component virtual void Update(float deltaTime); // Process input for this component virtual void ProcessInput(const uint8_t* keyState) {} - int GetUpdateOrder() const { return mUpdateOrder; } protected: // Owning actor - class Actor* mOwner; + class Actor* pOwner; // Update order of component int mUpdateOrder; -}; +}; \ No newline at end of file diff --git a/Chapter04/Enemy.cpp b/Chapter04/Enemy.cpp index ce3d5951..d1fe3dae 100644 --- a/Chapter04/Enemy.cpp +++ b/Chapter04/Enemy.cpp @@ -14,13 +14,12 @@ #include "Tile.h" #include "CircleComponent.h" #include +#include "AIState.h" -Enemy::Enemy(class Game* game) -:Actor(game) +Enemy::Enemy(class Game* game): Actor(game) { // Add to enemy vector game->GetEnemies().emplace_back(this); - SpriteComponent* sc = new SpriteComponent(this); sc->SetTexture(game->GetTexture("Assets/Airplane.png")); // Set position at start tile @@ -30,27 +29,30 @@ Enemy::Enemy(class Game* game) nc->SetForwardSpeed(150.0f); nc->StartPath(GetGame()->GetGrid()->GetStartTile()); // Setup a circle for collision - mCircle = new CircleComponent(this); - mCircle->SetRadius(25.0f); + pCircle = new CircleComponent(this); + pCircle->SetRadius(25.0f); + pAI = new AIComponent(this); + pAI->RegisterState(new AIPatrol(pAI)); + pAI->RegisterState(new AIDeath(pAI)); + pAI->ChangeState("Patrol"); } Enemy::~Enemy() { + pAI->ChangeState("Death"); // Remove from enemy vector - auto iter = std::find(GetGame()->GetEnemies().begin(), - GetGame()->GetEnemies().end(), - this); + auto iter = std::find(GetGame()->GetEnemies().begin(), GetGame()->GetEnemies().end(), this); GetGame()->GetEnemies().erase(iter); } void Enemy::UpdateActor(float deltaTime) { Actor::UpdateActor(deltaTime); - // Am I near the end tile? Vector2 diff = GetPosition() - GetGame()->GetGrid()->GetEndTile()->GetPosition(); if (Math::NearZero(diff.Length(), 10.0f)) { + pAI->ChangeState("Death"); SetState(EDead); } -} +} \ No newline at end of file diff --git a/Chapter04/Enemy.h b/Chapter04/Enemy.h index 72e33f08..0d3a00ff 100644 --- a/Chapter04/Enemy.h +++ b/Chapter04/Enemy.h @@ -8,14 +8,16 @@ #pragma once #include "Actor.h" +#include "AIComponent.h" -class Enemy : public Actor +class Enemy: public Actor { public: Enemy(class Game* game); ~Enemy(); void UpdateActor(float deltaTime) override; - class CircleComponent* GetCircle() { return mCircle; } + class CircleComponent* GetCircle() { return pCircle; } private: - class CircleComponent* mCircle; -}; + class CircleComponent* pCircle; + class AIComponent* pAI; +}; \ No newline at end of file diff --git a/Chapter04/Game.cpp b/Chapter04/Game.cpp index c044257c..87ac6802 100644 --- a/Chapter04/Game.cpp +++ b/Chapter04/Game.cpp @@ -16,13 +16,8 @@ #include "AIComponent.h" #include "AIState.h" -Game::Game() -:mWindow(nullptr) -,mRenderer(nullptr) -,mIsRunning(true) -,mUpdatingActors(false) +Game::Game(): pWindow(nullptr), pRenderer(nullptr), mIsRunning(true), mUpdatingActors(false) { - } bool Game::Initialize() @@ -32,16 +27,14 @@ bool Game::Initialize() SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } - - mWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 4)", 100, 100, 1024, 768, 0); - if (!mWindow) + pWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 4)", 100, 100, 1024, 768, 0); + if (!pWindow) { SDL_Log("Failed to create window: %s", SDL_GetError()); return false; } - - mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (!mRenderer) + pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!pRenderer) { SDL_Log("Failed to create renderer: %s", SDL_GetError()); return false; @@ -52,11 +45,8 @@ bool Game::Initialize() SDL_Log("Unable to initialize SDL_image: %s", SDL_GetError()); return false; } - LoadData(); - mTicksCount = SDL_GetTicks(); - return true; } @@ -82,26 +72,22 @@ void Game::ProcessInput() break; } } - const Uint8* keyState = SDL_GetKeyboardState(NULL); if (keyState[SDL_SCANCODE_ESCAPE]) { mIsRunning = false; } - if (keyState[SDL_SCANCODE_B]) { - mGrid->BuildTower(); + pGrid->BuildTower(); } - // Process mouse int x, y; Uint32 buttons = SDL_GetMouseState(&x, &y); if (SDL_BUTTON(buttons) & SDL_BUTTON_LEFT) { - mGrid->ProcessClick(x, y); + pGrid->ProcessClick(x, y); } - mUpdatingActors = true; for (auto actor : mActors) { @@ -112,33 +98,28 @@ void Game::ProcessInput() void Game::UpdateGame() { - // Compute delta time +// Compute delta time: // Wait until 16ms has elapsed since last frame - while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)) - ; - + while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)); float deltaTime = (SDL_GetTicks() - mTicksCount) / 1000.0f; if (deltaTime > 0.05f) { deltaTime = 0.05f; } mTicksCount = SDL_GetTicks(); - - // Update all actors +// Update all actors: mUpdatingActors = true; for (auto actor : mActors) { actor->Update(deltaTime); } mUpdatingActors = false; - // Move any pending actors to mActors for (auto pending : mPendingActors) { mActors.emplace_back(pending); } mPendingActors.clear(); - // Add any dead actors to a temp vector std::vector deadActors; for (auto actor : mActors) @@ -148,7 +129,6 @@ void Game::UpdateGame() deadActors.emplace_back(actor); } } - // Delete dead actors (which removes them from mActors) for (auto actor : deadActors) { @@ -158,21 +138,21 @@ void Game::UpdateGame() void Game::GenerateOutput() { - SDL_SetRenderDrawColor(mRenderer, 34, 139, 34, 255); - SDL_RenderClear(mRenderer); + SDL_SetRenderDrawColor(pRenderer, 34, 139, 34, 255); + SDL_RenderClear(pRenderer); // Draw all sprite components for (auto sprite : mSprites) { - sprite->Draw(mRenderer); + sprite->Draw(pRenderer); } - SDL_RenderPresent(mRenderer); + SDL_RenderPresent(pRenderer); } void Game::LoadData() { - mGrid = new Grid(this); + pGrid = new Grid(this); // For testing AIComponent //Actor* a = new Actor(this); @@ -193,7 +173,6 @@ void Game::UnloadData() { delete mActors.back(); } - // Destroy textures for (auto i : mTextures) { @@ -220,16 +199,14 @@ SDL_Texture* Game::GetTexture(const std::string& fileName) SDL_Log("Failed to load texture file %s", fileName.c_str()); return nullptr; } - // Create texture from surface - tex = SDL_CreateTextureFromSurface(mRenderer, surf); + tex = SDL_CreateTextureFromSurface(pRenderer, surf); SDL_FreeSurface(surf); if (!tex) { SDL_Log("Failed to convert surface to texture for %s", fileName.c_str()); return nullptr; } - mTextures.emplace(fileName.c_str(), tex); } return tex; @@ -239,8 +216,8 @@ void Game::Shutdown() { UnloadData(); IMG_Quit(); - SDL_DestroyRenderer(mRenderer); - SDL_DestroyWindow(mWindow); + SDL_DestroyRenderer(pRenderer); + SDL_DestroyWindow(pWindow); SDL_Quit(); } @@ -267,7 +244,6 @@ void Game::RemoveActor(Actor* actor) std::iter_swap(iter, mPendingActors.end() - 1); mPendingActors.pop_back(); } - // Is it in actors? iter = std::find(mActors.begin(), mActors.end(), actor); if (iter != mActors.end()) @@ -284,16 +260,13 @@ void Game::AddSprite(SpriteComponent* sprite) // (The first element with a higher draw order than me) int myDrawOrder = sprite->GetDrawOrder(); auto iter = mSprites.begin(); - for ( ; - iter != mSprites.end(); - ++iter) + for (; iter != mSprites.end(); ++iter) { if (myDrawOrder < (*iter)->GetDrawOrder()) { break; } } - // Inserts element before position of iterator mSprites.insert(iter, sprite); } @@ -308,7 +281,6 @@ void Game::RemoveSprite(SpriteComponent* sprite) Enemy* Game::GetNearestEnemy(const Vector2& pos) { Enemy* best = nullptr; - if (mEnemies.size() > 0) { best = mEnemies[0]; @@ -324,6 +296,5 @@ Enemy* Game::GetNearestEnemy(const Vector2& pos) } } } - return best; -} +} \ No newline at end of file diff --git a/Chapter04/Game.h b/Chapter04/Game.h index 56a0ecb4..577ea674 100644 --- a/Chapter04/Game.h +++ b/Chapter04/Game.h @@ -20,16 +20,12 @@ class Game bool Initialize(); void RunLoop(); void Shutdown(); - void AddActor(class Actor* actor); void RemoveActor(class Actor* actor); - void AddSprite(class SpriteComponent* sprite); void RemoveSprite(class SpriteComponent* sprite); - SDL_Texture* GetTexture(const std::string& fileName); - - class Grid* GetGrid() { return mGrid; } + class Grid* GetGrid() { return pGrid; } std::vector& GetEnemies() { return mEnemies; } class Enemy* GetNearestEnemy(const Vector2& pos); private: @@ -38,27 +34,22 @@ class Game void GenerateOutput(); void LoadData(); void UnloadData(); - // Map of textures loaded std::unordered_map mTextures; - // All the actors in the game std::vector mActors; // Any pending actors std::vector mPendingActors; - // All the sprite components drawn std::vector mSprites; - - SDL_Window* mWindow; - SDL_Renderer* mRenderer; + SDL_Window* pWindow; + SDL_Renderer* pRenderer; Uint32 mTicksCount; bool mIsRunning; // Track if we're updating actors right now bool mUpdatingActors; - // Game-specific std::vector mEnemies; - class Grid* mGrid; + class Grid* pGrid; float mNextEnemy; -}; +}; \ No newline at end of file diff --git a/Chapter04/Game.vcxproj b/Chapter04/Game.vcxproj index 27b091d3..ed536636 100644 --- a/Chapter04/Game.vcxproj +++ b/Chapter04/Game.vcxproj @@ -50,19 +50,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode diff --git a/Chapter04/Grid.cpp b/Chapter04/Grid.cpp index b81a7265..dd924d3f 100644 --- a/Chapter04/Grid.cpp +++ b/Chapter04/Grid.cpp @@ -12,9 +12,7 @@ #include "Enemy.h" #include -Grid::Grid(class Game* game) -:Actor(game) -,mSelectedTile(nullptr) +Grid::Grid(class Game* game): Actor(game), pSelectedTile(nullptr) { // 7 rows, 16 columns mTiles.resize(NumRows); @@ -22,7 +20,6 @@ Grid::Grid(class Game* game) { mTiles[i].resize(NumCols); } - // Create tiles for (size_t i = 0; i < NumRows; i++) { @@ -32,11 +29,9 @@ Grid::Grid(class Game* game) mTiles[i][j]->SetPosition(Vector2(TileSize/2.0f + j * TileSize, StartY + i * TileSize)); } } - // Set start/end tiles GetStartTile()->SetTileState(Tile::EStart); GetEndTile()->SetTileState(Tile::EBase); - // Set up adjacency lists for (size_t i = 0; i < NumRows; i++) { @@ -60,11 +55,9 @@ Grid::Grid(class Game* game) } } } - // Find path (in reverse) FindPath(GetEndTile(), GetStartTile()); UpdatePathTiles(GetStartTile()); - mNextEnemy = EnemyTime; } @@ -75,12 +68,12 @@ void Grid::SelectTile(size_t row, size_t col) if (tstate != Tile::EStart && tstate != Tile::EBase) { // Deselect previous one - if (mSelectedTile) + if (pSelectedTile) { - mSelectedTile->ToggleSelect(); + pSelectedTile->ToggleSelect(); } - mSelectedTile = mTiles[row][col]; - mSelectedTile->ToggleSelect(); + pSelectedTile = mTiles[row][col]; + pSelectedTile->ToggleSelect(); } } @@ -105,28 +98,24 @@ bool Grid::FindPath(Tile* start, Tile* goal) { for (size_t j = 0; j < NumCols; j++) { - mTiles[i][j]->g = 0.0f; + mTiles[i][j]->mG = 0.0f; mTiles[i][j]->mInOpenSet = false; mTiles[i][j]->mInClosedSet = false; } } - std::vector openSet; - // Set current node to start, and add to closed set Tile* current = start; current->mInClosedSet = true; - do { // Add adjacent nodes to open set - for (Tile* neighbor : current->mAdjacent) + for (Tile* neighbor: current->mAdjacent) { if (neighbor->mBlocked) { continue; } - // Only check nodes that aren't in the closed set if (!neighbor->mInClosedSet) { @@ -134,40 +123,37 @@ bool Grid::FindPath(Tile* start, Tile* goal) { // Not in the open set, so set parent neighbor->mParent = current; - neighbor->h = (neighbor->GetPosition() - goal->GetPosition()).Length(); + neighbor->mH = (neighbor->GetPosition() - goal->GetPosition()).Length(); // g(x) is the parent's g plus cost of traversing edge - neighbor->g = current->g + TileSize; - neighbor->f = neighbor->g + neighbor->h; + neighbor->mG = current->mG + TileSize; + neighbor->mF = neighbor->mG + neighbor->mH; openSet.emplace_back(neighbor); neighbor->mInOpenSet = true; } else { // Compute g(x) cost if current becomes the parent - float newG = current->g + TileSize; - if (newG < neighbor->g) + float newG = current->mG + TileSize; + if (newG < neighbor->mG) { // Adopt this node neighbor->mParent = current; - neighbor->g = newG; + neighbor->mG = newG; // f(x) changes because g(x) changes - neighbor->f = neighbor->g + neighbor->h; + neighbor->mF = neighbor->mG + neighbor->mH; } } } } - // If open set is empty, all possible paths are exhausted if (openSet.empty()) { break; } - // Find lowest cost node in open set - auto iter = std::min_element(openSet.begin(), openSet.end(), - [](Tile* a, Tile* b) { - return a->f < b->f; - }); + auto iter = std::min_element(openSet.begin(), openSet.end(), [](Tile* a, Tile* b) { + return a->mF < b->mF; + }); // Set to current and move from open to closed current = *iter; openSet.erase(iter); @@ -175,7 +161,6 @@ bool Grid::FindPath(Tile* start, Tile* goal) current->mInClosedSet = true; } while (current != goal); - // Did we find a path? return (current == goal) ? true : false; } @@ -193,7 +178,6 @@ void Grid::UpdatePathTiles(class Tile* start) } } } - Tile* t = start->mParent; while (t != GetEndTile()) { @@ -204,18 +188,18 @@ void Grid::UpdatePathTiles(class Tile* start) void Grid::BuildTower() { - if (mSelectedTile && !mSelectedTile->mBlocked) + if (pSelectedTile && !pSelectedTile->mBlocked) { - mSelectedTile->mBlocked = true; + pSelectedTile->mBlocked = true; if (FindPath(GetEndTile(), GetStartTile())) { Tower* t = new Tower(GetGame()); - t->SetPosition(mSelectedTile->GetPosition()); + t->SetPosition(pSelectedTile->GetPosition()); } else { // This tower would block the path, so don't allow build - mSelectedTile->mBlocked = false; + pSelectedTile->mBlocked = false; FindPath(GetEndTile(), GetStartTile()); } UpdatePathTiles(GetStartTile()); @@ -235,7 +219,6 @@ Tile* Grid::GetEndTile() void Grid::UpdateActor(float deltaTime) { Actor::UpdateActor(deltaTime); - // Is it time to spawn a new enemy? mNextEnemy -= deltaTime; if (mNextEnemy <= 0.0f) @@ -243,4 +226,4 @@ void Grid::UpdateActor(float deltaTime) new Enemy(GetGame()); mNextEnemy += EnemyTime; } -} +} \ No newline at end of file diff --git a/Chapter04/Grid.h b/Chapter04/Grid.h index a69ac893..bf1f461b 100644 --- a/Chapter04/Grid.h +++ b/Chapter04/Grid.h @@ -10,41 +10,31 @@ #include "Actor.h" #include -class Grid : public Actor +class Grid: public Actor { public: Grid(class Game* game); - // Handle a mouse click at the x/y screen locations void ProcessClick(int x, int y); - // Use A* to find a path bool FindPath(class Tile* start, class Tile* goal); - // Try to build a tower void BuildTower(); - // Get start/end tile class Tile* GetStartTile(); class Tile* GetEndTile(); - void UpdateActor(float deltaTime) override; private: // Select a specific tile void SelectTile(size_t row, size_t col); - // Update textures for tiles on path void UpdatePathTiles(class Tile* start); - // Currently selected tile - class Tile* mSelectedTile; - + class Tile* pSelectedTile; // 2D vector of tiles in grid std::vector> mTiles; - // Time until next enemy float mNextEnemy; - // Rows/columns in grid const size_t NumRows = 7; const size_t NumCols = 16; @@ -54,4 +44,4 @@ class Grid : public Actor const float TileSize = 64.0f; // Time between enemies const float EnemyTime = 1.5f; -}; +}; \ No newline at end of file diff --git a/Chapter04/Main.cpp b/Chapter04/Main.cpp index 22ea0c69..625e0599 100644 --- a/Chapter04/Main.cpp +++ b/Chapter04/Main.cpp @@ -18,4 +18,4 @@ int main(int argc, char** argv) } game.Shutdown(); return 0; -} +} \ No newline at end of file diff --git a/Chapter04/Math.cpp b/Chapter04/Math.cpp index a16e7261..c0d17507 100644 --- a/Chapter04/Math.cpp +++ b/Chapter04/Math.cpp @@ -39,7 +39,6 @@ static float m4Ident[4][4] = { 0.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }; - const Matrix4 Matrix4::Identity(m4Ident); const Quaternion Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f); @@ -56,12 +55,9 @@ Vector2 Vector2::Transform(const Vector2& vec, const Matrix3& mat, float w /*= 1 Vector3 Vector3::Transform(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/) { Vector3 retVal; - retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + - vec.z * mat.mat[2][0] + w * mat.mat[3][0]; - retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + - vec.z * mat.mat[2][1] + w * mat.mat[3][1]; - retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + - vec.z * mat.mat[2][2] + w * mat.mat[3][2]; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + vec.z * mat.mat[2][0] + w * mat.mat[3][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + vec.z * mat.mat[2][1] + w * mat.mat[3][1]; + retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + vec.z * mat.mat[2][2] + w * mat.mat[3][2]; //ignore w since we aren't returning a new value for it... return retVal; } @@ -70,14 +66,10 @@ Vector3 Vector3::Transform(const Vector3& vec, const Matrix4& mat, float w /*= 1 Vector3 Vector3::TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/) { Vector3 retVal; - retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + - vec.z * mat.mat[2][0] + w * mat.mat[3][0]; - retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + - vec.z * mat.mat[2][1] + w * mat.mat[3][1]; - retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + - vec.z * mat.mat[2][2] + w * mat.mat[3][2]; - float transformedW = vec.x * mat.mat[0][3] + vec.y * mat.mat[1][3] + - vec.z * mat.mat[2][3] + w * mat.mat[3][3]; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + vec.z * mat.mat[2][0] + w * mat.mat[3][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + vec.z * mat.mat[2][1] + w * mat.mat[3][1]; + retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + vec.z * mat.mat[2][2] + w * mat.mat[3][2]; + float transformedW = vec.x * mat.mat[0][3] + vec.y * mat.mat[1][3] + vec.z * mat.mat[2][3] + w * mat.mat[3][3]; if (!Math::NearZero(Math::Abs(transformedW))) { transformedW = 1.0f / transformedW; @@ -104,33 +96,28 @@ void Matrix4::Invert() float src[16]; float dst[16]; float det; - - // Transpose matrix +// Transpose matrix: // row 1 to col 1 src[0] = mat[0][0]; src[4] = mat[0][1]; src[8] = mat[0][2]; src[12] = mat[0][3]; - // row 2 to col 2 src[1] = mat[1][0]; src[5] = mat[1][1]; src[9] = mat[1][2]; src[13] = mat[1][3]; - // row 3 to col 3 src[2] = mat[2][0]; src[6] = mat[2][1]; src[10] = mat[2][2]; src[14] = mat[2][3]; - // row 4 to col 4 src[3] = mat[3][0]; src[7] = mat[3][1]; src[11] = mat[3][2]; src[15] = mat[3][3]; - - // Calculate cofactors +// Calculate cofactors: tmp[0] = src[10] * src[15]; tmp[1] = src[11] * src[14]; tmp[2] = src[9] * src[15]; @@ -142,8 +129,7 @@ void Matrix4::Invert() tmp[8] = src[8] * src[14]; tmp[9] = src[10] * src[12]; tmp[10] = src[8] * src[13]; - tmp[11] = src[9] * src[12]; - + tmp[11] = src[9] * src[12]; dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; @@ -160,7 +146,6 @@ void Matrix4::Invert() dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; - tmp[0] = src[2] * src[7]; tmp[1] = src[3] * src[6]; tmp[2] = src[1] * src[7]; @@ -173,7 +158,6 @@ void Matrix4::Invert() tmp[9] = src[2] * src[4]; tmp[10] = src[0] * src[5]; tmp[11] = src[1] * src[4]; - dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; @@ -190,17 +174,14 @@ void Matrix4::Invert() dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; - // Calculate determinant det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3]; - // Inverse of matrix is divided by determinant det = 1 / det; for (int j = 0; j < 16; j++) { dst[j] *= det; } - // Set it back for (int i = 0; i < 4; i++) { @@ -214,26 +195,21 @@ void Matrix4::Invert() Matrix4 Matrix4::CreateFromQuaternion(const class Quaternion& q) { float mat[4][4]; - mat[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z; mat[0][1] = 2.0f * q.x * q.y + 2.0f * q.w * q.z; mat[0][2] = 2.0f * q.x * q.z - 2.0f * q.w * q.y; mat[0][3] = 0.0f; - mat[1][0] = 2.0f * q.x * q.y - 2.0f * q.w * q.z; mat[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z; mat[1][2] = 2.0f * q.y * q.z + 2.0f * q.w * q.x; mat[1][3] = 0.0f; - mat[2][0] = 2.0f * q.x * q.z + 2.0f * q.w * q.y; mat[2][1] = 2.0f * q.y * q.z - 2.0f * q.w * q.x; mat[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y; mat[2][3] = 0.0f; - mat[3][0] = 0.0f; mat[3][1] = 0.0f; mat[3][2] = 0.0f; mat[3][3] = 1.0f; - return Matrix4(mat); -} +} \ No newline at end of file diff --git a/Chapter04/Math.h b/Chapter04/Math.h index 752963f1..a0f95813 100644 --- a/Chapter04/Math.h +++ b/Chapter04/Math.h @@ -24,12 +24,10 @@ namespace Math { return degrees * Pi / 180.0f; } - inline float ToDegrees(float radians) { return radians * 180.0f / Pi; } - inline bool NearZero(float val, float epsilon = 0.001f) { if (fabs(val) <= epsilon) @@ -41,70 +39,57 @@ namespace Math return false; } } - template T Max(const T& a, const T& b) { return (a < b ? b : a); } - template T Min(const T& a, const T& b) { return (a < b ? a : b); } - template T Clamp(const T& value, const T& lower, const T& upper) { return Min(upper, Max(lower, value)); } - inline float Abs(float value) { return fabs(value); } - inline float Cos(float angle) { return cosf(angle); } - inline float Sin(float angle) { return sinf(angle); } - inline float Tan(float angle) { return tanf(angle); } - inline float Acos(float value) { return acosf(value); } - inline float Atan2(float y, float x) { return atan2f(y, x); } - inline float Cot(float angle) { return 1.0f / Tan(angle); } - inline float Lerp(float a, float b, float f) { return a + f * (b - a); } - inline float Sqrt(float value) { return sqrtf(value); } - inline float Fmod(float numer, float denom) { return fmod(numer, denom); @@ -118,54 +103,42 @@ class Vector2 float x; float y; - Vector2() - :x(0.0f) - ,y(0.0f) + Vector2(): x(0.0f), y(0.0f) {} - - explicit Vector2(float inX, float inY) - :x(inX) - ,y(inY) + explicit Vector2(float inX, float inY): x(inX), y(inY) {} - // Set both components in one line void Set(float inX, float inY) { x = inX; y = inY; } - // Vector addition (a + b) friend Vector2 operator+(const Vector2& a, const Vector2& b) { return Vector2(a.x + b.x, a.y + b.y); } - // Vector subtraction (a - b) friend Vector2 operator-(const Vector2& a, const Vector2& b) { return Vector2(a.x - b.x, a.y - b.y); } - // Component-wise multiplication // (a.x * b.x, ...) friend Vector2 operator*(const Vector2& a, const Vector2& b) { return Vector2(a.x * b.x, a.y * b.y); } - // Scalar multiplication friend Vector2 operator*(const Vector2& vec, float scalar) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar multiplication friend Vector2 operator*(float scalar, const Vector2& vec) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar *= Vector2& operator*=(float scalar) { @@ -173,7 +146,6 @@ class Vector2 y *= scalar; return *this; } - // Vector += Vector2& operator+=(const Vector2& right) { @@ -181,7 +153,6 @@ class Vector2 y += right.y; return *this; } - // Vector -= Vector2& operator-=(const Vector2& right) { @@ -189,19 +160,16 @@ class Vector2 y -= right.y; return *this; } - // Length squared of vector float LengthSq() const { return (x*x + y*y); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -209,7 +177,6 @@ class Vector2 x /= length; y /= length; } - // Normalize the provided vector static Vector2 Normalize(const Vector2& vec) { @@ -217,25 +184,21 @@ class Vector2 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector2& a, const Vector2& b) { return (a.x * b.x + a.y * b.y); } - // Lerp from A to B by f static Vector2 Lerp(const Vector2& a, const Vector2& b, float f) { return Vector2(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector2 Reflect(const Vector2& v, const Vector2& n) { return v - 2.0f * Vector2::Dot(v, n) * n; } - // Transform vector by matrix static Vector2 Transform(const Vector2& vec, const class Matrix3& mat, float w = 1.0f); @@ -254,24 +217,15 @@ class Vector3 float y; float z; - Vector3() - :x(0.0f) - ,y(0.0f) - ,z(0.0f) + Vector3(): x(0.0f), y(0.0f), z(0.0f) {} - - explicit Vector3(float inX, float inY, float inZ) - :x(inX) - ,y(inY) - ,z(inZ) + explicit Vector3(float inX, float inY, float inZ): x(inX), y(inY), z(inZ) {} - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&x); } - // Set all three components in one line void Set(float inX, float inY, float inZ) { @@ -279,37 +233,31 @@ class Vector3 y = inY; z = inZ; } - // Vector addition (a + b) friend Vector3 operator+(const Vector3& a, const Vector3& b) { return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); } - // Vector subtraction (a - b) friend Vector3 operator-(const Vector3& a, const Vector3& b) { return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); } - // Component-wise multiplication friend Vector3 operator*(const Vector3& left, const Vector3& right) { return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); } - // Scalar multiplication friend Vector3 operator*(const Vector3& vec, float scalar) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar multiplication friend Vector3 operator*(float scalar, const Vector3& vec) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar *= Vector3& operator*=(float scalar) { @@ -318,7 +266,6 @@ class Vector3 z *= scalar; return *this; } - // Vector += Vector3& operator+=(const Vector3& right) { @@ -327,7 +274,6 @@ class Vector3 z += right.z; return *this; } - // Vector -= Vector3& operator-=(const Vector3& right) { @@ -336,19 +282,16 @@ class Vector3 z -= right.z; return *this; } - // Length squared of vector float LengthSq() const { return (x*x + y*y + z*z); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -357,7 +300,6 @@ class Vector3 y /= length; z /= length; } - // Normalize the provided vector static Vector3 Normalize(const Vector3& vec) { @@ -365,13 +307,11 @@ class Vector3 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector3& a, const Vector3& b) { return (a.x * b.x + a.y * b.y + a.z * b.z); } - // Cross product between two vectors (a cross b) static Vector3 Cross(const Vector3& a, const Vector3& b) { @@ -381,23 +321,19 @@ class Vector3 temp.z = a.x * b.y - a.y * b.x; return temp; } - // Lerp from A to B by f static Vector3 Lerp(const Vector3& a, const Vector3& b, float f) { return Vector3(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector3 Reflect(const Vector3& v, const Vector3& n) { return v - 2.0f * Vector3::Dot(v, n) * n; } - static Vector3 Transform(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); // This will transform the vector and renormalize the w component static Vector3 TransformWithPerspDiv(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); - // Transform a Vector3 by a quaternion static Vector3 Transform(const Vector3& v, const class Quaternion& q); @@ -422,18 +358,15 @@ class Matrix3 { *this = Matrix3::Identity; } - explicit Matrix3(float inMat[3][3]) { memcpy(mat, inMat, 9 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication friend Matrix3 operator*(const Matrix3& left, const Matrix3& right) { @@ -443,58 +376,47 @@ class Matrix3 left.mat[0][0] * right.mat[0][0] + left.mat[0][1] * right.mat[1][0] + left.mat[0][2] * right.mat[2][0]; - retVal.mat[0][1] = left.mat[0][0] * right.mat[0][1] + left.mat[0][1] * right.mat[1][1] + left.mat[0][2] * right.mat[2][1]; - retVal.mat[0][2] = left.mat[0][0] * right.mat[0][2] + left.mat[0][1] * right.mat[1][2] + left.mat[0][2] * right.mat[2][2]; - // row 1 retVal.mat[1][0] = left.mat[1][0] * right.mat[0][0] + left.mat[1][1] * right.mat[1][0] + left.mat[1][2] * right.mat[2][0]; - retVal.mat[1][1] = left.mat[1][0] * right.mat[0][1] + left.mat[1][1] * right.mat[1][1] + left.mat[1][2] * right.mat[2][1]; - retVal.mat[1][2] = left.mat[1][0] * right.mat[0][2] + left.mat[1][1] * right.mat[1][2] + left.mat[1][2] * right.mat[2][2]; - // row 2 retVal.mat[2][0] = left.mat[2][0] * right.mat[0][0] + left.mat[2][1] * right.mat[1][0] + left.mat[2][2] * right.mat[2][0]; - retVal.mat[2][1] = left.mat[2][0] * right.mat[0][1] + left.mat[2][1] * right.mat[1][1] + left.mat[2][2] * right.mat[2][1]; - retVal.mat[2][2] = left.mat[2][0] * right.mat[0][2] + left.mat[2][1] * right.mat[1][2] + left.mat[2][2] * right.mat[2][2]; - return retVal; } - Matrix3& operator*=(const Matrix3& right) { *this = *this * right; return *this; } - // Create a scale matrix with x and y scales static Matrix3 CreateScale(float xScale, float yScale) { @@ -506,18 +428,15 @@ class Matrix3 }; return Matrix3(temp); } - static Matrix3 CreateScale(const Vector2& scaleVector) { return CreateScale(scaleVector.x, scaleVector.y); } - // Create a scale matrix with a uniform factor static Matrix3 CreateScale(float scale) { return CreateScale(scale, scale); } - // Create a rotation matrix about the Z axis // theta is in radians static Matrix3 CreateRotation(float theta) @@ -530,7 +449,6 @@ class Matrix3 }; return Matrix3(temp); } - // Create a translation matrix (on the xy-plane) static Matrix3 CreateTranslation(const Vector2& trans) { @@ -542,7 +460,6 @@ class Matrix3 }; return Matrix3(temp); } - static const Matrix3 Identity; }; @@ -556,18 +473,15 @@ class Matrix4 { *this = Matrix4::Identity; } - explicit Matrix4(float inMat[4][4]) { memcpy(mat, inMat, 16 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication (a * b) friend Matrix4 operator*(const Matrix4& a, const Matrix4& b) { @@ -578,136 +492,113 @@ class Matrix4 a.mat[0][1] * b.mat[1][0] + a.mat[0][2] * b.mat[2][0] + a.mat[0][3] * b.mat[3][0]; - retVal.mat[0][1] = a.mat[0][0] * b.mat[0][1] + a.mat[0][1] * b.mat[1][1] + a.mat[0][2] * b.mat[2][1] + a.mat[0][3] * b.mat[3][1]; - retVal.mat[0][2] = a.mat[0][0] * b.mat[0][2] + a.mat[0][1] * b.mat[1][2] + a.mat[0][2] * b.mat[2][2] + a.mat[0][3] * b.mat[3][2]; - retVal.mat[0][3] = a.mat[0][0] * b.mat[0][3] + a.mat[0][1] * b.mat[1][3] + a.mat[0][2] * b.mat[2][3] + a.mat[0][3] * b.mat[3][3]; - // row 1 retVal.mat[1][0] = a.mat[1][0] * b.mat[0][0] + a.mat[1][1] * b.mat[1][0] + a.mat[1][2] * b.mat[2][0] + a.mat[1][3] * b.mat[3][0]; - retVal.mat[1][1] = a.mat[1][0] * b.mat[0][1] + a.mat[1][1] * b.mat[1][1] + a.mat[1][2] * b.mat[2][1] + a.mat[1][3] * b.mat[3][1]; - retVal.mat[1][2] = a.mat[1][0] * b.mat[0][2] + a.mat[1][1] * b.mat[1][2] + a.mat[1][2] * b.mat[2][2] + a.mat[1][3] * b.mat[3][2]; - retVal.mat[1][3] = a.mat[1][0] * b.mat[0][3] + a.mat[1][1] * b.mat[1][3] + a.mat[1][2] * b.mat[2][3] + a.mat[1][3] * b.mat[3][3]; - // row 2 retVal.mat[2][0] = a.mat[2][0] * b.mat[0][0] + a.mat[2][1] * b.mat[1][0] + a.mat[2][2] * b.mat[2][0] + a.mat[2][3] * b.mat[3][0]; - retVal.mat[2][1] = a.mat[2][0] * b.mat[0][1] + a.mat[2][1] * b.mat[1][1] + a.mat[2][2] * b.mat[2][1] + a.mat[2][3] * b.mat[3][1]; - retVal.mat[2][2] = a.mat[2][0] * b.mat[0][2] + a.mat[2][1] * b.mat[1][2] + a.mat[2][2] * b.mat[2][2] + a.mat[2][3] * b.mat[3][2]; - retVal.mat[2][3] = a.mat[2][0] * b.mat[0][3] + a.mat[2][1] * b.mat[1][3] + a.mat[2][2] * b.mat[2][3] + a.mat[2][3] * b.mat[3][3]; - // row 3 retVal.mat[3][0] = a.mat[3][0] * b.mat[0][0] + a.mat[3][1] * b.mat[1][0] + a.mat[3][2] * b.mat[2][0] + a.mat[3][3] * b.mat[3][0]; - retVal.mat[3][1] = a.mat[3][0] * b.mat[0][1] + a.mat[3][1] * b.mat[1][1] + a.mat[3][2] * b.mat[2][1] + a.mat[3][3] * b.mat[3][1]; - retVal.mat[3][2] = a.mat[3][0] * b.mat[0][2] + a.mat[3][1] * b.mat[1][2] + a.mat[3][2] * b.mat[2][2] + a.mat[3][3] * b.mat[3][2]; - retVal.mat[3][3] = a.mat[3][0] * b.mat[0][3] + a.mat[3][1] * b.mat[1][3] + a.mat[3][2] * b.mat[2][3] + a.mat[3][3] * b.mat[3][3]; - return retVal; } - Matrix4& operator*=(const Matrix4& right) { *this = *this * right; return *this; } - // Invert the matrix - super slow void Invert(); - // Get the translation component of the matrix Vector3 GetTranslation() const { return Vector3(mat[3][0], mat[3][1], mat[3][2]); } - // Get the X axis of the matrix (forward) Vector3 GetXAxis() const { return Vector3::Normalize(Vector3(mat[0][0], mat[0][1], mat[0][2])); } - // Get the Y axis of the matrix (left) Vector3 GetYAxis() const { return Vector3::Normalize(Vector3(mat[1][0], mat[1][1], mat[1][2])); } - // Get the Z axis of the matrix (up) Vector3 GetZAxis() const { return Vector3::Normalize(Vector3(mat[2][0], mat[2][1], mat[2][2])); } - // Extract the scale component from the matrix Vector3 GetScale() const { @@ -717,7 +608,6 @@ class Matrix4 retVal.z = Vector3(mat[2][0], mat[2][1], mat[2][2]).Length(); return retVal; } - // Create a scale matrix with x, y, and z scales static Matrix4 CreateScale(float xScale, float yScale, float zScale) { @@ -730,18 +620,15 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateScale(const Vector3& scaleVector) { return CreateScale(scaleVector.x, scaleVector.y, scaleVector.z); } - // Create a scale matrix with a uniform factor static Matrix4 CreateScale(float scale) { return CreateScale(scale, scale, scale); } - // Rotation about x-axis static Matrix4 CreateRotationX(float theta) { @@ -754,7 +641,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about y-axis static Matrix4 CreateRotationY(float theta) { @@ -767,7 +653,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about z-axis static Matrix4 CreateRotationZ(float theta) { @@ -780,10 +665,8 @@ class Matrix4 }; return Matrix4(temp); } - // Create a rotation matrix from a quaternion static Matrix4 CreateFromQuaternion(const class Quaternion& q); - static Matrix4 CreateTranslation(const Vector3& trans) { float temp[4][4] = @@ -795,7 +678,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { Vector3 zaxis = Vector3::Normalize(target - eye); @@ -805,7 +687,6 @@ class Matrix4 trans.x = -Vector3::Dot(xaxis, eye); trans.y = -Vector3::Dot(yaxis, eye); trans.z = -Vector3::Dot(zaxis, eye); - float temp[4][4] = { { xaxis.x, yaxis.x, zaxis.x, 0.0f }, @@ -815,7 +696,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateOrtho(float width, float height, float near, float far) { float temp[4][4] = @@ -827,7 +707,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreatePerspectiveFOV(float fovY, float width, float height, float near, float far) { float yScale = Math::Cot(fovY / 2.0f); @@ -841,7 +720,6 @@ class Matrix4 }; return Matrix4(temp); } - // Create "Simple" View-Projection Matrix from Chapter 6 static Matrix4 CreateSimpleViewProj(float width, float height) { @@ -854,7 +732,6 @@ class Matrix4 }; return Matrix4(temp); } - static const Matrix4 Identity; }; @@ -871,17 +748,13 @@ class Quaternion { *this = Quaternion::Identity; } - - // This directly sets the quaternion components -- - // don't use for axis/angle + // This directly sets the quaternion components -- don't use for axis/angle explicit Quaternion(float inX, float inY, float inZ, float inW) { Set(inX, inY, inZ, inW); } - // Construct the quaternion from an axis and angle - // It is assumed that axis is already normalized, - // and the angle is in radians + // It is assumed that axis is already normalized, and the angle is in radians explicit Quaternion(const Vector3& axis, float angle) { float scalar = Math::Sin(angle / 2.0f); @@ -890,7 +763,6 @@ class Quaternion z = axis.z * scalar; w = Math::Cos(angle / 2.0f); } - // Directly set the internal components void Set(float inX, float inY, float inZ, float inW) { @@ -899,24 +771,20 @@ class Quaternion z = inZ; w = inW; } - void Conjugate() { x *= -1.0f; y *= -1.0f; z *= -1.0f; } - float LengthSq() const { return (x*x + y*y + z*z + w*w); } - float Length() const { return Math::Sqrt(LengthSq()); } - void Normalize() { float length = Length(); @@ -925,7 +793,6 @@ class Quaternion z /= length; w /= length; } - // Normalize the provided quaternion static Quaternion Normalize(const Quaternion& q) { @@ -933,7 +800,6 @@ class Quaternion retVal.Normalize(); return retVal; } - // Linear interpolation static Quaternion Lerp(const Quaternion& a, const Quaternion& b, float f) { @@ -945,25 +811,20 @@ class Quaternion retVal.Normalize(); return retVal; } - static float Dot(const Quaternion& a, const Quaternion& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } - // Spherical Linear Interpolation static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float f) { float rawCosm = Quaternion::Dot(a, b); - float cosom = -rawCosm; if (rawCosm >= 0.0f) { cosom = rawCosm; } - float scale0, scale1; - if (cosom < 0.9999f) { const float omega = Math::Acos(cosom); @@ -973,17 +834,14 @@ class Quaternion } else { - // Use linear interpolation if the quaternions - // are collinear + // Use linear interpolation if the quaternions are collinear scale0 = 1.0f - f; scale1 = f; } - if (rawCosm < 0.0f) { scale1 = -scale1; } - Quaternion retVal; retVal.x = scale0 * a.x + scale1 * b.x; retVal.y = scale0 * a.y + scale1 * b.y; @@ -1007,11 +865,9 @@ class Quaternion retVal.x = newVec.x; retVal.y = newVec.y; retVal.z = newVec.z; - // Scalar component is: // ps * qs - pv . qv retVal.w = p.w * q.w - Vector3::Dot(pv, qv); - return retVal; } @@ -1030,4 +886,4 @@ namespace Color static const Vector3 LightBlue(0.68f, 0.85f, 0.9f); static const Vector3 LightPink(1.0f, 0.71f, 0.76f); static const Vector3 LightGreen(0.56f, 0.93f, 0.56f); -} +} \ No newline at end of file diff --git a/Chapter04/MoveComponent.cpp b/Chapter04/MoveComponent.cpp index cdf1fdf9..fad01c0d 100644 --- a/Chapter04/MoveComponent.cpp +++ b/Chapter04/MoveComponent.cpp @@ -9,27 +9,22 @@ #include "MoveComponent.h" #include "Actor.h" -MoveComponent::MoveComponent(class Actor* owner, int updateOrder) -:Component(owner, updateOrder) -,mAngularSpeed(0.0f) -,mForwardSpeed(0.0f) +MoveComponent::MoveComponent(class Actor* owner, int updateOrder): Component(owner, updateOrder), mAngularSpeed(0.0f), mForwardSpeed(0.0f) { - } void MoveComponent::Update(float deltaTime) { if (!Math::NearZero(mAngularSpeed)) { - float rot = mOwner->GetRotation(); + float rot = pOwner->GetRotation(); rot += mAngularSpeed * deltaTime; - mOwner->SetRotation(rot); + pOwner->SetRotation(rot); } - if (!Math::NearZero(mForwardSpeed)) { - Vector2 pos = mOwner->GetPosition(); - pos += mOwner->GetForward() * mForwardSpeed * deltaTime; - mOwner->SetPosition(pos); + Vector2 pos = pOwner->GetPosition(); + pos += pOwner->GetForward() * mForwardSpeed * deltaTime; + pOwner->SetPosition(pos); } -} +} \ No newline at end of file diff --git a/Chapter04/MoveComponent.h b/Chapter04/MoveComponent.h index def7d389..c737e66b 100644 --- a/Chapter04/MoveComponent.h +++ b/Chapter04/MoveComponent.h @@ -9,13 +9,12 @@ #pragma once #include "Component.h" -class MoveComponent : public Component +class MoveComponent: public Component { public: // Lower update order to update first MoveComponent(class Actor* owner, int updateOrder = 10); void Update(float deltaTime) override; - float GetAngularSpeed() const { return mAngularSpeed; } float GetForwardSpeed() const { return mForwardSpeed; } void SetAngularSpeed(float speed) { mAngularSpeed = speed; } @@ -23,4 +22,4 @@ class MoveComponent : public Component private: float mAngularSpeed; float mForwardSpeed; -}; +}; \ No newline at end of file diff --git a/Chapter04/NavComponent.cpp b/Chapter04/NavComponent.cpp index a80d38ce..ed95680e 100644 --- a/Chapter04/NavComponent.cpp +++ b/Chapter04/NavComponent.cpp @@ -9,41 +9,37 @@ #include "NavComponent.h" #include "Tile.h" -NavComponent::NavComponent(class Actor* owner, int updateOrder) -:MoveComponent(owner, updateOrder) -,mNextNode(nullptr) +NavComponent::NavComponent(class Actor* owner, int updateOrder): MoveComponent(owner, updateOrder), pNextNode(nullptr) { - } void NavComponent::Update(float deltaTime) { - if (mNextNode) + if (pNextNode) { // If we're at the next node, advance along path - Vector2 diff = mOwner->GetPosition() - mNextNode->GetPosition(); + Vector2 diff = pOwner->GetPosition() - pNextNode->GetPosition(); if (Math::NearZero(diff.Length(), 2.0f)) { - mNextNode = mNextNode->GetParent(); - TurnTo(mNextNode->GetPosition()); + pNextNode = pNextNode->GetParent(); + TurnTo(pNextNode->GetPosition()); } } - MoveComponent::Update(deltaTime); } void NavComponent::StartPath(const Tile* start) { - mNextNode = start->GetParent(); - TurnTo(mNextNode->GetPosition()); + pNextNode = start->GetParent(); + TurnTo(pNextNode->GetPosition()); } void NavComponent::TurnTo(const Vector2& pos) { // Vector from me to pos - Vector2 dir = pos - mOwner->GetPosition(); + Vector2 dir = pos - pOwner->GetPosition(); // New angle is just atan2 of this dir vector // (Negate y because +y is down on screen) float angle = Math::Atan2(-dir.y, dir.x); - mOwner->SetRotation(angle); -} + pOwner->SetRotation(angle); +} \ No newline at end of file diff --git a/Chapter04/NavComponent.h b/Chapter04/NavComponent.h index b79c721f..acd98437 100644 --- a/Chapter04/NavComponent.h +++ b/Chapter04/NavComponent.h @@ -10,7 +10,7 @@ #include "MoveComponent.h" #include "Math.h" -class NavComponent : public MoveComponent +class NavComponent: public MoveComponent { public: // Lower update order to update first @@ -19,5 +19,5 @@ class NavComponent : public MoveComponent void StartPath(const class Tile* start); void TurnTo(const Vector2& pos); private: - const class Tile* mNextNode; -}; + const class Tile* pNextNode; +}; \ No newline at end of file diff --git a/Chapter04/Search.cpp b/Chapter04/Search.cpp index ce1e6f41..b0491b1c 100644 --- a/Chapter04/Search.cpp +++ b/Chapter04/Search.cpp @@ -20,8 +20,8 @@ struct Graph struct WeightedEdge { // Which nodes are connected by this edge? - struct WeightedGraphNode* mFrom; - struct WeightedGraphNode* mTo; + struct WeightedGraphNode* pFrom; + struct WeightedGraphNode* pTo; // Weight of this edge float mWeight; }; @@ -38,47 +38,42 @@ struct WeightedGraph struct GBFSScratch { - const WeightedEdge* mParentEdge = nullptr; + const WeightedEdge* pParentEdge = nullptr; float mHeuristic = 0.0f; bool mInOpenSet = false; bool mInClosedSet = false; }; -using GBFSMap = -std::unordered_map; +using GBFSMap = std::unordered_map; struct AStarScratch { - const WeightedEdge* mParentEdge = nullptr; + const WeightedEdge* pParentEdge = nullptr; float mHeuristic = 0.0f; float mActualFromStart = 0.0f; bool mInOpenSet = false; bool mInClosedSet = false; }; -using AStarMap = -std::unordered_map; +using AStarMap = std::unordered_map; float ComputeHeuristic(const WeightedGraphNode* a, const WeightedGraphNode* b) { return 0.0f; } -bool AStar(const WeightedGraph& g, const WeightedGraphNode* start, - const WeightedGraphNode* goal, AStarMap& outMap) +bool AStar(const WeightedGraph& g, const WeightedGraphNode* start, const WeightedGraphNode* goal, AStarMap& outMap) { std::vector openSet; - // Set current node to start, and mark in closed set const WeightedGraphNode* current = start; outMap[current].mInClosedSet = true; - do { // Add adjacent nodes to open set for (const WeightedEdge* edge : current->mEdges) { - const WeightedGraphNode* neighbor = edge->mTo; + const WeightedGraphNode* neighbor = edge->pTo; // Get scratch data for this node AStarScratch& data = outMap[neighbor]; // Only check nodes that aren't in the closed set @@ -87,11 +82,10 @@ bool AStar(const WeightedGraph& g, const WeightedGraphNode* start, if (!data.mInOpenSet) { // Not in the open set, so parent must be current - data.mParentEdge = edge; + data.pParentEdge = edge; data.mHeuristic = ComputeHeuristic(neighbor, goal); // Actual cost is the parent's plus cost of traversing edge - data.mActualFromStart = outMap[current].mActualFromStart + - edge->mWeight; + data.mActualFromStart = outMap[current].mActualFromStart + edge->mWeight; data.mInOpenSet = true; openSet.emplace_back(neighbor); } @@ -102,22 +96,19 @@ bool AStar(const WeightedGraph& g, const WeightedGraphNode* start, if (newG < data.mActualFromStart) { // Current should adopt this node - data.mParentEdge = edge; + data.pParentEdge = edge; data.mActualFromStart = newG; } } } } - // If open set is empty, all possible paths are exhausted if (openSet.empty()) { break; } - // Find lowest cost node in open set - auto iter = std::min_element(openSet.begin(), openSet.end(), - [&outMap](const WeightedGraphNode* a, const WeightedGraphNode* b) { + auto iter = std::min_element(openSet.begin(), openSet.end(), [&outMap](const WeightedGraphNode* a, const WeightedGraphNode* b) { // Calculate f(x) for nodes a/b float fOfA = outMap[a].mHeuristic + outMap[a].mActualFromStart; float fOfB = outMap[b].mHeuristic + outMap[b].mActualFromStart; @@ -129,67 +120,57 @@ bool AStar(const WeightedGraph& g, const WeightedGraphNode* start, outMap[current].mInOpenSet = true; outMap[current].mInClosedSet = true; } while (current != goal); - // Did we find a path? return (current == goal) ? true : false; } -bool GBFS(const WeightedGraph& g, const WeightedGraphNode* start, - const WeightedGraphNode* goal, GBFSMap& outMap) +bool GBFS(const WeightedGraph& g, const WeightedGraphNode* start, const WeightedGraphNode* goal, GBFSMap& outMap) { std::vector openSet; - // Set current node to start, and mark in closed set const WeightedGraphNode* current = start; outMap[current].mInClosedSet = true; - do { // Add adjacent nodes to open set for (const WeightedEdge* edge : current->mEdges) { // Get scratch data for this node - GBFSScratch& data = outMap[edge->mTo]; + GBFSScratch& data = outMap[edge->pTo]; // Add it only if it's not in the closed set if (!data.mInClosedSet) { // Set the adjacent node's parent edge - data.mParentEdge = edge; + data.pParentEdge = edge; if (!data.mInOpenSet) { // Compute the heuristic for this node, and add to open set - data.mHeuristic = ComputeHeuristic(edge->mTo, goal); + data.mHeuristic = ComputeHeuristic(edge->pTo, goal); data.mInOpenSet = true; - openSet.emplace_back(edge->mTo); + openSet.emplace_back(edge->pTo); } } } - // If open set is empty, all possible paths are exhausted if (openSet.empty()) { break; } - // Find lowest cost node in open set - auto iter = std::min_element(openSet.begin(), openSet.end(), - [&outMap](const WeightedGraphNode* a, const WeightedGraphNode* b) { + auto iter = std::min_element(openSet.begin(), openSet.end(), [&outMap](const WeightedGraphNode* a, const WeightedGraphNode* b) { return outMap[a].mHeuristic < outMap[b].mHeuristic; }); - // Set to current and move from open to closed current = *iter; openSet.erase(iter); outMap[current].mInOpenSet = false; outMap[current].mInClosedSet = true; } while (current != goal); - // Did we find a path? return (current == goal) ? true : false; } -using NodeToParentMap = -std::unordered_map; +using NodeToParentMap = std::unordered_map; bool BFS(const Graph& graph, const GraphNode* start, const GraphNode* goal, NodeToParentMap& outMap) { @@ -199,7 +180,6 @@ bool BFS(const Graph& graph, const GraphNode* start, const GraphNode* goal, Node std::queue q; // Enqueue the first node q.emplace(start); - while (!q.empty()) { // Dequeue a node @@ -210,7 +190,6 @@ bool BFS(const Graph& graph, const GraphNode* start, const GraphNode* goal, Node pathFound = true; break; } - // Enqueue adjacent nodes that aren't already in the queue for (const GraphNode* node : current->mAdjacent) { @@ -225,7 +204,6 @@ bool BFS(const Graph& graph, const GraphNode* start, const GraphNode* goal, Node } } } - return pathFound; } @@ -240,7 +218,6 @@ void testBFS() g.mNodes.emplace_back(node); } } - for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) @@ -264,7 +241,6 @@ void testBFS() } } } - NodeToParentMap map; bool found = BFS(g, g.mNodes[0], g.mNodes[9], map); std::cout << found << '\n'; @@ -281,7 +257,6 @@ void testHeuristic(bool useAStar) g.mNodes.emplace_back(node); } } - for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) @@ -290,32 +265,32 @@ void testHeuristic(bool useAStar) if (i > 0) { WeightedEdge* e = new WeightedEdge; - e->mFrom = node; - e->mTo = g.mNodes[(i - 1) * 5 + j]; + e->pFrom = node; + e->pTo = g.mNodes[(i - 1) * 5 + j]; e->mWeight = 1.0f; node->mEdges.emplace_back(e); } if (i < 4) { WeightedEdge* e = new WeightedEdge; - e->mFrom = node; - e->mTo = g.mNodes[(i + 1) * 5 + j]; + e->pFrom = node; + e->pTo = g.mNodes[(i + 1) * 5 + j]; e->mWeight = 1.0f; node->mEdges.emplace_back(e); } if (j > 0) { WeightedEdge* e = new WeightedEdge; - e->mFrom = node; - e->mTo = g.mNodes[i * 5 + j - 1]; + e->pFrom = node; + e->pTo = g.mNodes[i * 5 + j - 1]; e->mWeight = 1.0f; node->mEdges.emplace_back(e); } if (j < 4) { WeightedEdge* e = new WeightedEdge; - e->mFrom = node; - e->mTo = g.mNodes[i * 5 + j + 1]; + e->pFrom = node; + e->pTo = g.mNodes[i * 5 + j + 1]; e->mWeight = 1.0f; node->mEdges.emplace_back(e); } @@ -382,7 +357,6 @@ float GetScore(const GameState& state) same = false; } } - if (same) { if (v == GameState::X) @@ -395,7 +369,6 @@ float GetScore(const GameState& state) } } } - // Are any of the columns the same? for (int j = 0; j < 3; j++) { @@ -408,7 +381,6 @@ float GetScore(const GameState& state) same = false; } } - if (same) { if (v == GameState::X) @@ -421,12 +393,8 @@ float GetScore(const GameState& state) } } } - // What about diagonals? - if (((state.mBoard[0][0] == state.mBoard[1][1]) && - (state.mBoard[1][1] == state.mBoard[2][2])) || - ((state.mBoard[2][0] == state.mBoard[1][1]) && - (state.mBoard[1][1] == state.mBoard[0][2]))) + if (((state.mBoard[0][0] == state.mBoard[1][1]) && (state.mBoard[1][1] == state.mBoard[2][2])) || ((state.mBoard[2][0] == state.mBoard[1][1]) && (state.mBoard[1][1] == state.mBoard[0][2]))) { if (state.mBoard[1][1] == GameState::X) { @@ -450,7 +418,6 @@ float MaxPlayer(const GTNode* node) { return GetScore(node->mState); } - float maxValue = -std::numeric_limits::infinity(); // Find the subtree with the maximum value for (const GTNode* child : node->mChildren) @@ -467,7 +434,6 @@ float MinPlayer(const GTNode* node) { return GetScore(node->mState); } - float minValue = std::numeric_limits::infinity(); // Find the subtree with the minimum value for (const GTNode* child : node->mChildren) @@ -482,7 +448,7 @@ const GTNode* MinimaxDecide(const GTNode* root) // Find the subtree with the maximum value, and save the choice const GTNode* choice = nullptr; float maxValue = -std::numeric_limits::infinity(); - for (const GTNode* child : root->mChildren) + for (const GTNode* child: root->mChildren) { float v = MinPlayer(child); if (v > maxValue) @@ -503,7 +469,6 @@ float AlphaBetaMax(const GTNode* node, float alpha, float beta) { return GetScore(node->mState); } - float maxValue = -std::numeric_limits::infinity(); // Find the subtree with the maximum value for (const GTNode* child : node->mChildren) @@ -525,7 +490,6 @@ float AlphaBetaMin(const GTNode* node, float alpha, float beta) { return GetScore(node->mState); } - float minValue = std::numeric_limits::infinity(); // Find the subtree with the minimum value for (const GTNode* child : node->mChildren) @@ -570,8 +534,7 @@ void testTicTac() root->mState.mBoard[2][0] = GameState::X; root->mState.mBoard[2][1] = GameState::Empty; root->mState.mBoard[2][2] = GameState::Empty; - GenStates(root, true); const GTNode* choice = AlphaBetaDecide(root); std::cout << choice->mChildren.size(); -} +} \ No newline at end of file diff --git a/Chapter04/SpriteComponent.cpp b/Chapter04/SpriteComponent.cpp index 56884fbc..e661e423 100644 --- a/Chapter04/SpriteComponent.cpp +++ b/Chapter04/SpriteComponent.cpp @@ -10,47 +10,35 @@ #include "Actor.h" #include "Game.h" -SpriteComponent::SpriteComponent(Actor* owner, int drawOrder) - :Component(owner) - ,mTexture(nullptr) - ,mDrawOrder(drawOrder) - ,mTexWidth(0) - ,mTexHeight(0) +SpriteComponent::SpriteComponent(Actor* owner, int drawOrder): Component(owner), pTexture(nullptr), mDrawOrder(drawOrder), mTexWidth(0), mTexHeight(0) { - mOwner->GetGame()->AddSprite(this); + pOwner->GetGame()->AddSprite(this); } SpriteComponent::~SpriteComponent() { - mOwner->GetGame()->RemoveSprite(this); + pOwner->GetGame()->RemoveSprite(this); } void SpriteComponent::Draw(SDL_Renderer* renderer) { - if (mTexture) + if (pTexture) { SDL_Rect r; // Scale the width/height by owner's scale - r.w = static_cast(mTexWidth * mOwner->GetScale()); - r.h = static_cast(mTexHeight * mOwner->GetScale()); + r.w = static_cast(mTexWidth * pOwner->GetScale()); + r.h = static_cast(mTexHeight * pOwner->GetScale()); // Center the rectangle around the position of the owner - r.x = static_cast(mOwner->GetPosition().x - r.w / 2); - r.y = static_cast(mOwner->GetPosition().y - r.h / 2); - + r.x = static_cast(pOwner->GetPosition().x - r.w / 2); + r.y = static_cast(pOwner->GetPosition().y - r.h / 2); // Draw (have to convert angle from radians to degrees, and clockwise to counter) - SDL_RenderCopyEx(renderer, - mTexture, - nullptr, - &r, - -Math::ToDegrees(mOwner->GetRotation()), - nullptr, - SDL_FLIP_NONE); + SDL_RenderCopyEx(renderer, pTexture, nullptr, &r, -Math::ToDegrees(pOwner->GetRotation()), nullptr, SDL_FLIP_NONE); } } void SpriteComponent::SetTexture(SDL_Texture* texture) { - mTexture = texture; + pTexture = texture; // Set width/height SDL_QueryTexture(texture, nullptr, nullptr, &mTexWidth, &mTexHeight); -} +} \ No newline at end of file diff --git a/Chapter04/SpriteComponent.h b/Chapter04/SpriteComponent.h index c430e888..70357ba9 100644 --- a/Chapter04/SpriteComponent.h +++ b/Chapter04/SpriteComponent.h @@ -9,22 +9,20 @@ #pragma once #include "Component.h" #include "SDL/SDL.h" -class SpriteComponent : public Component +class SpriteComponent: public Component { public: // (Lower draw order corresponds with further back) SpriteComponent(class Actor* owner, int drawOrder = 100); ~SpriteComponent(); - virtual void Draw(SDL_Renderer* renderer); virtual void SetTexture(SDL_Texture* texture); - int GetDrawOrder() const { return mDrawOrder; } int GetTexHeight() const { return mTexHeight; } int GetTexWidth() const { return mTexWidth; } protected: - SDL_Texture* mTexture; + SDL_Texture* pTexture; int mDrawOrder; int mTexWidth; int mTexHeight; -}; +}; \ No newline at end of file diff --git a/Chapter04/Tile.cpp b/Chapter04/Tile.cpp index 90e5c781..57c34b64 100644 --- a/Chapter04/Tile.cpp +++ b/Chapter04/Tile.cpp @@ -10,18 +10,9 @@ #include "SpriteComponent.h" #include "Game.h" -Tile::Tile(class Game* game) -:Actor(game) -,mParent(nullptr) -,f(0.0f) -,g(0.0f) -,h(0.0f) -,mBlocked(false) -,mSprite(nullptr) -,mTileState(EDefault) -,mSelected(false) +Tile::Tile(class Game* game): Actor(game), mParent(nullptr), mF(0.0f), mG(0.0f), mH(0.0f), mBlocked(false), pSprite(nullptr), mTileState(EDefault), mSelected(false) { - mSprite = new SpriteComponent(this); + pSprite = new SpriteComponent(this); UpdateTexture(); } @@ -62,5 +53,5 @@ void Tile::UpdateTexture() text = "Assets/TileBrown.png"; break; } - mSprite->SetTexture(GetGame()->GetTexture(text)); -} + pSprite->SetTexture(GetGame()->GetTexture(text)); +} \ No newline at end of file diff --git a/Chapter04/Tile.h b/Chapter04/Tile.h index f3e90d12..0281de90 100644 --- a/Chapter04/Tile.h +++ b/Chapter04/Tile.h @@ -10,7 +10,7 @@ #include "Actor.h" #include -class Tile : public Actor +class Tile: public Actor { public: friend class Grid; @@ -21,9 +21,7 @@ class Tile : public Actor EStart, EBase }; - Tile(class Game* game); - void SetTileState(TileState state); TileState GetTileState() const { return mTileState; } void ToggleSelect(); @@ -32,15 +30,14 @@ class Tile : public Actor // For pathfinding std::vector mAdjacent; Tile* mParent; - float f; - float g; - float h; + float mF; + float mG; + float mH; bool mInOpenSet; bool mInClosedSet; bool mBlocked; - void UpdateTexture(); - class SpriteComponent* mSprite; + class SpriteComponent* pSprite; TileState mTileState; bool mSelected; -}; +}; \ No newline at end of file diff --git a/Chapter04/Tower.cpp b/Chapter04/Tower.cpp index 20d60dea..c8493b46 100644 --- a/Chapter04/Tower.cpp +++ b/Chapter04/Tower.cpp @@ -12,29 +12,31 @@ #include "Game.h" #include "Enemy.h" #include "Bullet.h" +#include "AIState.h" -Tower::Tower(class Game* game) -:Actor(game) +Tower::Tower(class Game* game): Actor(game) { SpriteComponent* sc = new SpriteComponent(this, 200); sc->SetTexture(game->GetTexture("Assets/Tower.png")); - - mMove = new MoveComponent(this); - //mMove->SetAngularSpeed(Math::Pi); - + pMove = new MoveComponent(this); + //pMove->SetAngularSpeed(Math::Pi); + pAI = new AIComponent(this); + pAI->RegisterState(new AIPatrol(pAI)); + pAI->RegisterState(new AIAttack(pAI)); + pAI->ChangeState("Patrol"); mNextAttack = AttackTime; } void Tower::UpdateActor(float deltaTime) { Actor::UpdateActor(deltaTime); - mNextAttack -= deltaTime; if (mNextAttack <= 0.0f) { Enemy* e = GetGame()->GetNearestEnemy(GetPosition()); if (e != nullptr) { + pAI->ChangeState("Attack"); // Vector from me to enemy Vector2 dir = e->GetPosition() - GetPosition(); float dist = dir.Length(); @@ -48,6 +50,10 @@ void Tower::UpdateActor(float deltaTime) b->SetRotation(GetRotation()); } } + else + { + pAI->ChangeState("Patrol"); + } mNextAttack += AttackTime; } -} +} \ No newline at end of file diff --git a/Chapter04/Tower.h b/Chapter04/Tower.h index bfbf12ff..67365bfd 100644 --- a/Chapter04/Tower.h +++ b/Chapter04/Tower.h @@ -8,15 +8,17 @@ #pragma once #include "Actor.h" +#include "AIComponent.h" -class Tower : public Actor +class Tower: public Actor { public: Tower(class Game* game); void UpdateActor(float deltaTime) override; private: - class MoveComponent* mMove; + class MoveComponent* pMove; + class AIComponent* pAI; float mNextAttack; const float AttackTime = 2.5f; const float AttackRange = 100.0f; -}; +}; \ No newline at end of file diff --git a/Chapter05/Game.vcxproj b/Chapter05/Game.vcxproj index b0bd2f45..15c0a42b 100644 --- a/Chapter05/Game.vcxproj +++ b/Chapter05/Game.vcxproj @@ -56,19 +56,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 00000000..0990299d --- /dev/null +++ b/TODO.txt @@ -0,0 +1,35 @@ +TODO: +5.1 - Updating exercise +5.2 - Add vertex color (RGB) to sprite shader +6.1 - Multiple mesh shaders +6.2 - Point lights +7.1 - Add velocity to the listener +7.2 - Virtual positions for events +8.1 - Controller support +8.2 - Abstract input mapping +9.1 - User controlled camera rotation +9.2 - Modified spline camera +10.1 - Add jumping +10.2 - SweepAndPrune() all 3 axes +10.3 - Intersect OBB and OBB +11.1 - Add Main Menu +11.2 - Better radar +11.3 - Radar arrow target +12.1 - Animated bone positions +12.2 - Blending animations +13.1 - Add specular component to lights +13.2 - Add spot lights +14.1 - Only save changes +14.2 - Create binary for animations +Skipped: +1.1 - I do not care about Pong +1.2 - More Pong +2.1 - Theory stuff +2.2 - 2D stuff +2.3 - 2D stuff +3.1 - Theory stuff +3.2 - 2D stuff +3.3 - 2D stuff +4.2 - I do not care about Connect 4 +Done: +4.1 - State Machine \ No newline at end of file From 9fbd928570f8dc435cc33cc8b8f8180e387dcecd Mon Sep 17 00:00:00 2001 From: bobnone Date: Wed, 18 May 2022 15:15:22 -0500 Subject: [PATCH 2/6] Finished 5.1 --- Chapter05/Actor.cpp | 23 +---- Chapter05/Actor.h | 16 +-- Chapter05/Asteroid.cpp | 18 +--- Chapter05/Asteroid.h | 9 +- Chapter05/CircleComponent.cpp | 13 +-- Chapter05/CircleComponent.h | 6 +- Chapter05/Component.cpp | 10 +- Chapter05/Component.h | 8 +- Chapter05/Game.cpp | 117 +++++++++------------- Chapter05/Game.h | 25 ++--- Chapter05/InputComponent.cpp | 13 +-- Chapter05/InputComponent.h | 7 +- Chapter05/Laser.cpp | 16 ++- Chapter05/Laser.h | 7 +- Chapter05/Main.cpp | 2 +- Chapter05/Math.cpp | 23 +---- Chapter05/Math.h | 167 ++++--------------------------- Chapter05/MoveComponent.cpp | 19 ++-- Chapter05/MoveComponent.h | 5 +- Chapter05/Random.cpp | 2 +- Chapter05/Random.h | 7 +- Chapter05/Shader.cpp | 39 ++------ Chapter05/Shader.h | 7 +- Chapter05/Shaders/Basic.frag | 5 +- Chapter05/Shaders/Basic.vert | 2 +- Chapter05/Shaders/Sprite.frag | 4 +- Chapter05/Shaders/Sprite.vert | 4 +- Chapter05/Shaders/Transform.vert | 3 +- Chapter05/Ship.cpp | 8 +- Chapter05/Ship.h | 3 +- Chapter05/SpriteComponent.cpp | 32 ++---- Chapter05/SpriteComponent.h | 8 +- Chapter05/Texture.cpp | 23 +---- Chapter05/Texture.h | 5 +- Chapter05/VertexArray.cpp | 18 +--- Chapter05/VertexArray.h | 5 +- TODO.txt | 4 +- 37 files changed, 176 insertions(+), 507 deletions(-) diff --git a/Chapter05/Actor.cpp b/Chapter05/Actor.cpp index 738d508f..494f52ec 100644 --- a/Chapter05/Actor.cpp +++ b/Chapter05/Actor.cpp @@ -11,20 +11,14 @@ #include "Component.h" #include -Actor::Actor(Game* game) - :mState(EActive) - ,mPosition(Vector2::Zero) - ,mScale(1.0f) - ,mRotation(0.0f) - ,mGame(game) - ,mRecomputeWorldTransform(true) +Actor::Actor(Game* game): mState(EActive), mPosition(Vector2::Zero), mScale(1.0f), mRotation(0.0f), pGame(game), mRecomputeWorldTransform(true) { - mGame->AddActor(this); + pGame->AddActor(this); } Actor::~Actor() { - mGame->RemoveActor(this); + pGame->RemoveActor(this); // Need to delete components // Because ~Component calls RemoveComponent, need a different style loop while (!mComponents.empty()) @@ -38,10 +32,8 @@ void Actor::Update(float deltaTime) if (mState == EActive) { ComputeWorldTransform(); - UpdateComponents(deltaTime); UpdateActor(deltaTime); - ComputeWorldTransform(); } } @@ -67,7 +59,6 @@ void Actor::ProcessInput(const uint8_t* keyState) { comp->ProcessInput(keyState); } - ActorInput(keyState); } } @@ -85,7 +76,6 @@ void Actor::ComputeWorldTransform() mWorldTransform = Matrix4::CreateScale(mScale); mWorldTransform *= Matrix4::CreateRotationZ(mRotation); mWorldTransform *= Matrix4::CreateTranslation(Vector3(mPosition.x, mPosition.y, 0.0f)); - // Inform components world transform updated for (auto comp : mComponents) { @@ -100,16 +90,13 @@ void Actor::AddComponent(Component* component) // (The first element with a order higher than me) int myOrder = component->GetUpdateOrder(); auto iter = mComponents.begin(); - for (; - iter != mComponents.end(); - ++iter) + for (; iter != mComponents.end(); ++iter) { if (myOrder < (*iter)->GetUpdateOrder()) { break; } } - // Inserts element before position of iterator mComponents.insert(iter, component); } @@ -121,4 +108,4 @@ void Actor::RemoveComponent(Component* component) { mComponents.erase(iter); } -} +} \ No newline at end of file diff --git a/Chapter05/Actor.h b/Chapter05/Actor.h index 7a41bd47..fee90714 100644 --- a/Chapter05/Actor.h +++ b/Chapter05/Actor.h @@ -20,22 +20,18 @@ class Actor EPaused, EDead }; - Actor(class Game* game); virtual ~Actor(); - // Update function called from Game (not overridable) void Update(float deltaTime); // Updates all the components attached to the actor (not overridable) void UpdateComponents(float deltaTime); // Any actor-specific update code (overridable) virtual void UpdateActor(float deltaTime); - // ProcessInput function called from Game (not overridable) void ProcessInput(const uint8_t* keyState); // Any actor-specific input code (overridable) virtual void ActorInput(const uint8_t* keyState); - // Getters/setters const Vector2& GetPosition() const { return mPosition; } void SetPosition(const Vector2& pos) { mPosition = pos; mRecomputeWorldTransform = true; } @@ -43,32 +39,24 @@ class Actor void SetScale(float scale) { mScale = scale; mRecomputeWorldTransform = true; } float GetRotation() const { return mRotation; } void SetRotation(float rotation) { mRotation = rotation; mRecomputeWorldTransform = true; } - void ComputeWorldTransform(); const Matrix4& GetWorldTransform() const { return mWorldTransform; } - Vector2 GetForward() const { return Vector2(Math::Cos(mRotation), Math::Sin(mRotation)); } - State GetState() const { return mState; } void SetState(State state) { mState = state; } - - class Game* GetGame() { return mGame; } - - + class Game* GetGame() { return pGame; } // Add/remove components void AddComponent(class Component* component); void RemoveComponent(class Component* component); private: // Actor's state State mState; - // Transform Matrix4 mWorldTransform; Vector2 mPosition; float mScale; float mRotation; bool mRecomputeWorldTransform; - std::vector mComponents; - class Game* mGame; + class Game* pGame; }; diff --git a/Chapter05/Asteroid.cpp b/Chapter05/Asteroid.cpp index 9bcaa1e1..098c6607 100644 --- a/Chapter05/Asteroid.cpp +++ b/Chapter05/Asteroid.cpp @@ -13,29 +13,21 @@ #include "Random.h" #include "CircleComponent.h" -Asteroid::Asteroid(Game* game) - :Actor(game) - ,mCircle(nullptr) +Asteroid::Asteroid(Game* game): Actor(game), pCircle(nullptr) { // Initialize to random position/orientation - Vector2 randPos = Random::GetVector(Vector2(-512.0f, -384.0f), - Vector2(512.0f, 384.0f)); + Vector2 randPos = Random::GetVector(Vector2(-512.0f, -384.0f), Vector2(512.0f, 384.0f)); SetPosition(randPos); - SetRotation(Random::GetFloatRange(0.0f, Math::TwoPi)); - // Create a sprite component SpriteComponent* sc = new SpriteComponent(this); sc->SetTexture(game->GetTexture("Assets/Asteroid.png")); - // Create a move component, and set a forward speed MoveComponent* mc = new MoveComponent(this); mc->SetForwardSpeed(150.0f); - // Create a circle component (for collision) - mCircle = new CircleComponent(this); - mCircle->SetRadius(40.0f); - + pCircle = new CircleComponent(this); + pCircle->SetRadius(40.0f); // Add to mAsteroids in game game->AddAsteroid(this); } @@ -43,4 +35,4 @@ Asteroid::Asteroid(Game* game) Asteroid::~Asteroid() { GetGame()->RemoveAsteroid(this); -} +} \ No newline at end of file diff --git a/Chapter05/Asteroid.h b/Chapter05/Asteroid.h index 45305770..fd64416a 100644 --- a/Chapter05/Asteroid.h +++ b/Chapter05/Asteroid.h @@ -8,13 +8,12 @@ #pragma once #include "Actor.h" -class Asteroid : public Actor +class Asteroid: public Actor { public: Asteroid(class Game* game); ~Asteroid(); - - class CircleComponent* GetCircle() { return mCircle; } + class CircleComponent* GetCircle() { return pCircle; } private: - class CircleComponent* mCircle; -}; + class CircleComponent* pCircle; +}; \ No newline at end of file diff --git a/Chapter05/CircleComponent.cpp b/Chapter05/CircleComponent.cpp index d41aab2c..e0e31b71 100644 --- a/Chapter05/CircleComponent.cpp +++ b/Chapter05/CircleComponent.cpp @@ -9,21 +9,18 @@ #include "CircleComponent.h" #include "Actor.h" -CircleComponent::CircleComponent(class Actor* owner) -:Component(owner) -,mRadius(0.0f) +CircleComponent::CircleComponent(class Actor* owner): Component(owner), mRadius(0.0f) { - } const Vector2& CircleComponent::GetCenter() const { - return mOwner->GetPosition(); + return pOwner->GetPosition(); } float CircleComponent::GetRadius() const { - return mOwner->GetScale() * mRadius; + return pOwner->GetScale() * mRadius; } bool Intersect(const CircleComponent& a, const CircleComponent& b) @@ -31,10 +28,8 @@ bool Intersect(const CircleComponent& a, const CircleComponent& b) // Calculate distance squared Vector2 diff = a.GetCenter() - b.GetCenter(); float distSq = diff.LengthSq(); - // Calculate sum of radii squared float radiiSq = a.GetRadius() + b.GetRadius(); radiiSq *= radiiSq; - return distSq <= radiiSq; -} +} \ No newline at end of file diff --git a/Chapter05/CircleComponent.h b/Chapter05/CircleComponent.h index 4eecb2a4..113bd5e5 100644 --- a/Chapter05/CircleComponent.h +++ b/Chapter05/CircleComponent.h @@ -10,17 +10,15 @@ #include "Component.h" #include "Math.h" -class CircleComponent : public Component +class CircleComponent: public Component { public: CircleComponent(class Actor* owner); - void SetRadius(float radius) { mRadius = radius; } float GetRadius() const; - const Vector2& GetCenter() const; private: float mRadius; }; -bool Intersect(const CircleComponent& a, const CircleComponent& b); +bool Intersect(const CircleComponent& a, const CircleComponent& b); \ No newline at end of file diff --git a/Chapter05/Component.cpp b/Chapter05/Component.cpp index c4ed432d..5446d684 100644 --- a/Chapter05/Component.cpp +++ b/Chapter05/Component.cpp @@ -9,19 +9,17 @@ #include "Component.h" #include "Actor.h" -Component::Component(Actor* owner, int updateOrder) - :mOwner(owner) - ,mUpdateOrder(updateOrder) +Component::Component(Actor* owner, int updateOrder): pOwner(owner), mUpdateOrder(updateOrder) { // Add to actor's vector of components - mOwner->AddComponent(this); + pOwner->AddComponent(this); } Component::~Component() { - mOwner->RemoveComponent(this); + pOwner->RemoveComponent(this); } void Component::Update(float deltaTime) { -} +} \ No newline at end of file diff --git a/Chapter05/Component.h b/Chapter05/Component.h index e2be424b..a72aa198 100644 --- a/Chapter05/Component.h +++ b/Chapter05/Component.h @@ -12,8 +12,7 @@ class Component { public: - // Constructor - // (the lower the update order, the earlier the component updates) + // Constructor (the lower the update order, the earlier the component updates) Component(class Actor* owner, int updateOrder = 100); // Destructor virtual ~Component(); @@ -23,11 +22,10 @@ class Component virtual void ProcessInput(const uint8_t* keyState) {} // Called when world transform changes virtual void OnUpdateWorldTransform() { } - int GetUpdateOrder() const { return mUpdateOrder; } protected: // Owning actor - class Actor* mOwner; + class Actor* pOwner; // Update order of component int mUpdateOrder; -}; +}; \ No newline at end of file diff --git a/Chapter05/Game.cpp b/Chapter05/Game.cpp index e18e90a3..f7ea6e7e 100644 --- a/Chapter05/Game.cpp +++ b/Chapter05/Game.cpp @@ -19,13 +19,8 @@ #include "Asteroid.h" #include "Random.h" -Game::Game() -:mWindow(nullptr) -,mSpriteShader(nullptr) -,mIsRunning(true) -,mUpdatingActors(false) +Game::Game(): pWindow(nullptr), pSpriteShader(nullptr), mIsRunning(true), mUpdatingActors(false), mBGColor(Color::Black), mBGDirection(true) { - } bool Game::Initialize() @@ -35,8 +30,7 @@ bool Game::Initialize() SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } - - // Set OpenGL attributes +// Set OpenGL attributes: // Use the core OpenGL profile SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // Specify version 3.3 @@ -51,18 +45,14 @@ bool Game::Initialize() SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Force OpenGL to use hardware acceleration SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); - - mWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 5)", 100, 100, - 1024, 768, SDL_WINDOW_OPENGL); - if (!mWindow) + pWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 5)", 100, 100, 1024, 768, SDL_WINDOW_OPENGL); + if (!pWindow) { SDL_Log("Failed to create window: %s", SDL_GetError()); return false; } - // Create an OpenGL context - mContext = SDL_GL_CreateContext(mWindow); - + mContext = SDL_GL_CreateContext(pWindow); // Initialize GLEW glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) @@ -70,25 +60,18 @@ bool Game::Initialize() SDL_Log("Failed to initialize GLEW."); return false; } - - // On some platforms, GLEW will emit a benign error code, - // so clear it + // On some platforms, GLEW will emit a benign error code, so clear it glGetError(); - // Make sure we can create/compile shaders if (!LoadShaders()) { SDL_Log("Failed to load shaders."); return false; } - // Create quad for drawing sprites CreateSpriteVerts(); - LoadData(); - mTicksCount = SDL_GetTicks(); - return true; } @@ -98,7 +81,7 @@ void Game::RunLoop() { ProcessInput(); UpdateGame(); - GenerateOutput(); + //GenerateOutput(); } } @@ -114,15 +97,13 @@ void Game::ProcessInput() break; } } - const Uint8* keyState = SDL_GetKeyboardState(NULL); if (keyState[SDL_SCANCODE_ESCAPE]) { mIsRunning = false; } - mUpdatingActors = true; - for (auto actor : mActors) + for (auto actor: mActors) { actor->ProcessInput(keyState); } @@ -133,24 +114,20 @@ void Game::UpdateGame() { // Compute delta time // Wait until 16ms has elapsed since last frame - while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)) - ; - + while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)); float deltaTime = (SDL_GetTicks() - mTicksCount) / 1000.0f; if (deltaTime > 0.05f) { deltaTime = 0.05f; } mTicksCount = SDL_GetTicks(); - - // Update all actors +// Update all actors: mUpdatingActors = true; for (auto actor : mActors) { actor->Update(deltaTime); } mUpdatingActors = false; - // Move any pending actors to mActors for (auto pending : mPendingActors) { @@ -158,7 +135,6 @@ void Game::UpdateGame() mActors.emplace_back(pending); } mPendingActors.clear(); - // Add any dead actors to a temp vector std::vector deadActors; for (auto actor : mActors) @@ -168,50 +144,60 @@ void Game::UpdateGame() deadActors.emplace_back(actor); } } - // Delete dead actors (which removes them from mActors) for (auto actor : deadActors) { delete actor; } + GenerateOutput(deltaTime); } -void Game::GenerateOutput() +void Game::GenerateOutput(float deltaTime) { - // Set the clear color to grey - glClearColor(0.86f, 0.86f, 0.86f, 1.0f); + if (mBGDirection && (mBGColor.z < Color::Blue.z)) + { + // Update the current background color + mBGColor.z += 0.1f * deltaTime; + } + else if (!mBGDirection && (mBGColor.z > Color::Black.z)) + { + // Update the current background color + mBGColor.z -= 0.1f * deltaTime; + } + else + { + mBGDirection = !mBGDirection; + } + // Set the clear color to the current background color + glClearColor(mBGColor.x, mBGColor.y, mBGColor.z, 1.0f); // Clear the color buffer glClear(GL_COLOR_BUFFER_BIT); - // Draw all sprite components // Enable alpha blending on the color buffer glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // Set shader/vao as active - mSpriteShader->SetActive(); - mSpriteVerts->SetActive(); - for (auto sprite : mSprites) + pSpriteShader->SetActive(); + pSpriteVerts->SetActive(); + for (auto sprite: mSprites) { - sprite->Draw(mSpriteShader); + sprite->Draw(pSpriteShader); } - // Swap the buffers - SDL_GL_SwapWindow(mWindow); + SDL_GL_SwapWindow(pWindow); } bool Game::LoadShaders() { - mSpriteShader = new Shader(); - if (!mSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag")) + pSpriteShader = new Shader(); + if (!pSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag")) { return false; } - - mSpriteShader->SetActive(); + pSpriteShader->SetActive(); // Set the view-projection matrix Matrix4 viewProj = Matrix4::CreateSimpleViewProj(1024.f, 768.f); - mSpriteShader->SetMatrixUniform("uViewProj", viewProj); + pSpriteShader->SetMatrixUniform("uViewProj", viewProj); return true; } @@ -223,21 +209,18 @@ void Game::CreateSpriteVerts() 0.5f, -0.5f, 0.f, 1.f, 1.f, // bottom right -0.5f, -0.5f, 0.f, 0.f, 1.f // bottom left }; - unsigned int indices[] = { 0, 1, 2, 2, 3, 0 }; - - mSpriteVerts = new VertexArray(vertices, 4, indices, 6); + pSpriteVerts = new VertexArray(vertices, 4, indices, 6); } void Game::LoadData() { // Create player's ship - mShip = new Ship(this); - mShip->SetRotation(Math::PiOver2); - + pShip = new Ship(this); + pShip->SetRotation(Math::PiOver2); // Create asteroids const int numAsteroids = 20; for (int i = 0; i < numAsteroids; i++) @@ -254,7 +237,6 @@ void Game::UnloadData() { delete mActors.back(); } - // Destroy textures for (auto i : mTextures) { @@ -295,8 +277,7 @@ void Game::AddAsteroid(Asteroid* ast) void Game::RemoveAsteroid(Asteroid* ast) { - auto iter = std::find(mAsteroids.begin(), - mAsteroids.end(), ast); + auto iter = std::find(mAsteroids.begin(), mAsteroids.end(), ast); if (iter != mAsteroids.end()) { mAsteroids.erase(iter); @@ -306,11 +287,11 @@ void Game::RemoveAsteroid(Asteroid* ast) void Game::Shutdown() { UnloadData(); - delete mSpriteVerts; - mSpriteShader->Unload(); - delete mSpriteShader; + delete pSpriteVerts; + pSpriteShader->Unload(); + delete pSpriteShader; SDL_GL_DeleteContext(mContext); - SDL_DestroyWindow(mWindow); + SDL_DestroyWindow(pWindow); SDL_Quit(); } @@ -337,7 +318,6 @@ void Game::RemoveActor(Actor* actor) std::iter_swap(iter, mPendingActors.end() - 1); mPendingActors.pop_back(); } - // Is it in actors? iter = std::find(mActors.begin(), mActors.end(), actor); if (iter != mActors.end()) @@ -354,16 +334,13 @@ void Game::AddSprite(SpriteComponent* sprite) // (The first element with a higher draw order than me) int myDrawOrder = sprite->GetDrawOrder(); auto iter = mSprites.begin(); - for (; - iter != mSprites.end(); - ++iter) + for (; iter != mSprites.end(); ++iter) { if (myDrawOrder < (*iter)->GetDrawOrder()) { break; } } - // Inserts element before position of iterator mSprites.insert(iter, sprite); } @@ -372,4 +349,4 @@ void Game::RemoveSprite(SpriteComponent* sprite) { auto iter = std::find(mSprites.begin(), mSprites.end(), sprite); mSprites.erase(iter); -} +} \ No newline at end of file diff --git a/Chapter05/Game.h b/Chapter05/Game.h index d5c22637..fe695626 100644 --- a/Chapter05/Game.h +++ b/Chapter05/Game.h @@ -20,15 +20,11 @@ class Game bool Initialize(); void RunLoop(); void Shutdown(); - void AddActor(class Actor* actor); void RemoveActor(class Actor* actor); - void AddSprite(class SpriteComponent* sprite); void RemoveSprite(class SpriteComponent* sprite); - class Texture* GetTexture(const std::string& fileName); - // Game-specific (add/remove asteroid) void AddAsteroid(class Asteroid* ast); void RemoveAsteroid(class Asteroid* ast); @@ -36,36 +32,33 @@ class Game private: void ProcessInput(); void UpdateGame(); - void GenerateOutput(); + void GenerateOutput(float deltaTime); bool LoadShaders(); void CreateSpriteVerts(); void LoadData(); void UnloadData(); - + // Map of textures loaded std::unordered_map mTextures; - // All the actors in the game std::vector mActors; // Any pending actors std::vector mPendingActors; - // All the sprite components drawn std::vector mSprites; - // Sprite shader - class Shader* mSpriteShader; + class Shader* pSpriteShader; // Sprite vertex array - class VertexArray* mSpriteVerts; - - SDL_Window* mWindow; + class VertexArray* pSpriteVerts; + SDL_Window* pWindow; SDL_GLContext mContext; Uint32 mTicksCount; bool mIsRunning; // Track if we're updating actors right now bool mUpdatingActors; - // Game-specific - class Ship* mShip; + class Ship* pShip; std::vector mAsteroids; -}; + Vector3 mBGColor; + bool mBGDirection; +}; \ No newline at end of file diff --git a/Chapter05/InputComponent.cpp b/Chapter05/InputComponent.cpp index 148ffc95..1e5acfbd 100644 --- a/Chapter05/InputComponent.cpp +++ b/Chapter05/InputComponent.cpp @@ -9,14 +9,8 @@ #include "InputComponent.h" #include "Actor.h" -InputComponent::InputComponent(class Actor* owner) -:MoveComponent(owner) -,mForwardKey(0) -,mBackKey(0) -,mClockwiseKey(0) -,mCounterClockwiseKey(0) -{ - +InputComponent::InputComponent(class Actor* owner): MoveComponent(owner), mForwardKey(0), mBackKey(0), mClockwiseKey(0), mCounterClockwiseKey(0) +{ } void InputComponent::ProcessInput(const uint8_t* keyState) @@ -32,7 +26,6 @@ void InputComponent::ProcessInput(const uint8_t* keyState) forwardSpeed -= mMaxForwardSpeed; } SetForwardSpeed(forwardSpeed); - // Calculate angular speed for MoveComponent float angularSpeed = 0.0f; if (keyState[mClockwiseKey]) @@ -44,4 +37,4 @@ void InputComponent::ProcessInput(const uint8_t* keyState) angularSpeed -= mMaxAngularSpeed; } SetAngularSpeed(angularSpeed); -} +} \ No newline at end of file diff --git a/Chapter05/InputComponent.h b/Chapter05/InputComponent.h index 57b32ccb..163f85ee 100644 --- a/Chapter05/InputComponent.h +++ b/Chapter05/InputComponent.h @@ -10,14 +10,12 @@ #include "MoveComponent.h" #include -class InputComponent : public MoveComponent +class InputComponent: public MoveComponent { public: // Lower update order to update first InputComponent(class Actor* owner); - void ProcessInput(const uint8_t* keyState) override; - // Getters/setters for private variables float GetMaxForward() const { return mMaxForwardSpeed; } float GetMaxAngular() const { return mMaxAngularSpeed; } @@ -25,7 +23,6 @@ class InputComponent : public MoveComponent int GetBackKey() const { return mBackKey; } int GetClockwiseKey() const { return mClockwiseKey; } int GetCounterClockwiseKey() const { return mCounterClockwiseKey; } - void SetMaxForwardSpeed(float speed) { mMaxForwardSpeed = speed; } void SetMaxAngularSpeed(float speed) { mMaxAngularSpeed = speed; } void SetForwardKey(int key) { mForwardKey = key; } @@ -42,4 +39,4 @@ class InputComponent : public MoveComponent // Keys for angular movement int mClockwiseKey; int mCounterClockwiseKey; -}; +}; \ No newline at end of file diff --git a/Chapter05/Laser.cpp b/Chapter05/Laser.cpp index a03c1981..9a1a7d71 100644 --- a/Chapter05/Laser.cpp +++ b/Chapter05/Laser.cpp @@ -13,21 +13,17 @@ #include "CircleComponent.h" #include "Asteroid.h" -Laser::Laser(Game* game) - :Actor(game) - ,mDeathTimer(1.0f) +Laser::Laser(Game* game): Actor(game), mDeathTimer(1.0f) { // Create a sprite component SpriteComponent* sc = new SpriteComponent(this); sc->SetTexture(game->GetTexture("Assets/Laser.png")); - // Create a move component, and set a forward speed MoveComponent* mc = new MoveComponent(this); mc->SetForwardSpeed(800.0f); - // Create a circle component (for collision) - mCircle = new CircleComponent(this); - mCircle->SetRadius(11.0f); + pCircle = new CircleComponent(this); + pCircle->SetRadius(11.0f); } void Laser::UpdateActor(float deltaTime) @@ -41,9 +37,9 @@ void Laser::UpdateActor(float deltaTime) else { // Do we intersect with an asteroid? - for (auto ast : GetGame()->GetAsteroids()) + for (auto ast: GetGame()->GetAsteroids()) { - if (Intersect(*mCircle, *(ast->GetCircle()))) + if (Intersect(*pCircle, *(ast->GetCircle()))) { // The first asteroid we intersect with, // set ourselves and the asteroid to dead @@ -53,4 +49,4 @@ void Laser::UpdateActor(float deltaTime) } } } -} +} \ No newline at end of file diff --git a/Chapter05/Laser.h b/Chapter05/Laser.h index f1afd638..c995e91e 100644 --- a/Chapter05/Laser.h +++ b/Chapter05/Laser.h @@ -8,13 +8,12 @@ #pragma once #include "Actor.h" -class Laser : public Actor +class Laser: public Actor { public: Laser(class Game* game); - void UpdateActor(float deltaTime) override; private: - class CircleComponent* mCircle; + class CircleComponent* pCircle; float mDeathTimer; -}; +}; \ No newline at end of file diff --git a/Chapter05/Main.cpp b/Chapter05/Main.cpp index 22ea0c69..625e0599 100644 --- a/Chapter05/Main.cpp +++ b/Chapter05/Main.cpp @@ -18,4 +18,4 @@ int main(int argc, char** argv) } game.Shutdown(); return 0; -} +} \ No newline at end of file diff --git a/Chapter05/Math.cpp b/Chapter05/Math.cpp index a16e7261..44ff7ddd 100644 --- a/Chapter05/Math.cpp +++ b/Chapter05/Math.cpp @@ -39,7 +39,6 @@ static float m4Ident[4][4] = { 0.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }; - const Matrix4 Matrix4::Identity(m4Ident); const Quaternion Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f); @@ -104,33 +103,28 @@ void Matrix4::Invert() float src[16]; float dst[16]; float det; - - // Transpose matrix +// Transpose matrix: // row 1 to col 1 src[0] = mat[0][0]; src[4] = mat[0][1]; src[8] = mat[0][2]; src[12] = mat[0][3]; - // row 2 to col 2 src[1] = mat[1][0]; src[5] = mat[1][1]; src[9] = mat[1][2]; src[13] = mat[1][3]; - // row 3 to col 3 src[2] = mat[2][0]; src[6] = mat[2][1]; src[10] = mat[2][2]; src[14] = mat[2][3]; - // row 4 to col 4 src[3] = mat[3][0]; src[7] = mat[3][1]; src[11] = mat[3][2]; src[15] = mat[3][3]; - - // Calculate cofactors +// Calculate cofactors: tmp[0] = src[10] * src[15]; tmp[1] = src[11] * src[14]; tmp[2] = src[9] * src[15]; @@ -143,7 +137,6 @@ void Matrix4::Invert() tmp[9] = src[10] * src[12]; tmp[10] = src[8] * src[13]; tmp[11] = src[9] * src[12]; - dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; @@ -160,7 +153,6 @@ void Matrix4::Invert() dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; - tmp[0] = src[2] * src[7]; tmp[1] = src[3] * src[6]; tmp[2] = src[1] * src[7]; @@ -173,7 +165,6 @@ void Matrix4::Invert() tmp[9] = src[2] * src[4]; tmp[10] = src[0] * src[5]; tmp[11] = src[1] * src[4]; - dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; @@ -190,17 +181,14 @@ void Matrix4::Invert() dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; - // Calculate determinant det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3]; - // Inverse of matrix is divided by determinant det = 1 / det; for (int j = 0; j < 16; j++) { dst[j] *= det; } - // Set it back for (int i = 0; i < 4; i++) { @@ -214,26 +202,21 @@ void Matrix4::Invert() Matrix4 Matrix4::CreateFromQuaternion(const class Quaternion& q) { float mat[4][4]; - mat[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z; mat[0][1] = 2.0f * q.x * q.y + 2.0f * q.w * q.z; mat[0][2] = 2.0f * q.x * q.z - 2.0f * q.w * q.y; mat[0][3] = 0.0f; - mat[1][0] = 2.0f * q.x * q.y - 2.0f * q.w * q.z; mat[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z; mat[1][2] = 2.0f * q.y * q.z + 2.0f * q.w * q.x; mat[1][3] = 0.0f; - mat[2][0] = 2.0f * q.x * q.z + 2.0f * q.w * q.y; mat[2][1] = 2.0f * q.y * q.z - 2.0f * q.w * q.x; mat[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y; mat[2][3] = 0.0f; - mat[3][0] = 0.0f; mat[3][1] = 0.0f; mat[3][2] = 0.0f; mat[3][3] = 1.0f; - return Matrix4(mat); -} +} \ No newline at end of file diff --git a/Chapter05/Math.h b/Chapter05/Math.h index 752963f1..281e0f37 100644 --- a/Chapter05/Math.h +++ b/Chapter05/Math.h @@ -24,12 +24,10 @@ namespace Math { return degrees * Pi / 180.0f; } - inline float ToDegrees(float radians) { return radians * 180.0f / Pi; } - inline bool NearZero(float val, float epsilon = 0.001f) { if (fabs(val) <= epsilon) @@ -41,70 +39,57 @@ namespace Math return false; } } - template T Max(const T& a, const T& b) { return (a < b ? b : a); } - template T Min(const T& a, const T& b) { return (a < b ? a : b); } - template T Clamp(const T& value, const T& lower, const T& upper) { return Min(upper, Max(lower, value)); } - inline float Abs(float value) { return fabs(value); } - inline float Cos(float angle) { return cosf(angle); } - inline float Sin(float angle) { return sinf(angle); } - inline float Tan(float angle) { return tanf(angle); } - inline float Acos(float value) { return acosf(value); } - inline float Atan2(float y, float x) { return atan2f(y, x); } - inline float Cot(float angle) { return 1.0f / Tan(angle); } - inline float Lerp(float a, float b, float f) { return a + f * (b - a); } - inline float Sqrt(float value) { return sqrtf(value); } - inline float Fmod(float numer, float denom) { return fmod(numer, denom); @@ -118,54 +103,41 @@ class Vector2 float x; float y; - Vector2() - :x(0.0f) - ,y(0.0f) + Vector2(): x(0.0f), y(0.0f) {} - - explicit Vector2(float inX, float inY) - :x(inX) - ,y(inY) + explicit Vector2(float inX, float inY): x(inX), y(inY) {} - // Set both components in one line void Set(float inX, float inY) { x = inX; y = inY; } - // Vector addition (a + b) friend Vector2 operator+(const Vector2& a, const Vector2& b) { return Vector2(a.x + b.x, a.y + b.y); } - // Vector subtraction (a - b) friend Vector2 operator-(const Vector2& a, const Vector2& b) { return Vector2(a.x - b.x, a.y - b.y); } - // Component-wise multiplication - // (a.x * b.x, ...) friend Vector2 operator*(const Vector2& a, const Vector2& b) { return Vector2(a.x * b.x, a.y * b.y); } - // Scalar multiplication friend Vector2 operator*(const Vector2& vec, float scalar) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar multiplication friend Vector2 operator*(float scalar, const Vector2& vec) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar *= Vector2& operator*=(float scalar) { @@ -173,7 +145,6 @@ class Vector2 y *= scalar; return *this; } - // Vector += Vector2& operator+=(const Vector2& right) { @@ -181,7 +152,6 @@ class Vector2 y += right.y; return *this; } - // Vector -= Vector2& operator-=(const Vector2& right) { @@ -189,19 +159,16 @@ class Vector2 y -= right.y; return *this; } - // Length squared of vector float LengthSq() const { return (x*x + y*y); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -209,7 +176,6 @@ class Vector2 x /= length; y /= length; } - // Normalize the provided vector static Vector2 Normalize(const Vector2& vec) { @@ -217,25 +183,21 @@ class Vector2 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector2& a, const Vector2& b) { return (a.x * b.x + a.y * b.y); } - // Lerp from A to B by f static Vector2 Lerp(const Vector2& a, const Vector2& b, float f) { return Vector2(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector2 Reflect(const Vector2& v, const Vector2& n) { return v - 2.0f * Vector2::Dot(v, n) * n; } - // Transform vector by matrix static Vector2 Transform(const Vector2& vec, const class Matrix3& mat, float w = 1.0f); @@ -254,24 +216,15 @@ class Vector3 float y; float z; - Vector3() - :x(0.0f) - ,y(0.0f) - ,z(0.0f) + Vector3(): x(0.0f), y(0.0f), z(0.0f) {} - - explicit Vector3(float inX, float inY, float inZ) - :x(inX) - ,y(inY) - ,z(inZ) + explicit Vector3(float inX, float inY, float inZ): x(inX), y(inY), z(inZ) {} - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&x); } - // Set all three components in one line void Set(float inX, float inY, float inZ) { @@ -279,37 +232,31 @@ class Vector3 y = inY; z = inZ; } - // Vector addition (a + b) friend Vector3 operator+(const Vector3& a, const Vector3& b) { return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); } - // Vector subtraction (a - b) friend Vector3 operator-(const Vector3& a, const Vector3& b) { return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); } - // Component-wise multiplication friend Vector3 operator*(const Vector3& left, const Vector3& right) { return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); } - // Scalar multiplication friend Vector3 operator*(const Vector3& vec, float scalar) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar multiplication friend Vector3 operator*(float scalar, const Vector3& vec) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar *= Vector3& operator*=(float scalar) { @@ -318,7 +265,6 @@ class Vector3 z *= scalar; return *this; } - // Vector += Vector3& operator+=(const Vector3& right) { @@ -327,7 +273,6 @@ class Vector3 z += right.z; return *this; } - // Vector -= Vector3& operator-=(const Vector3& right) { @@ -336,19 +281,26 @@ class Vector3 z -= right.z; return *this; } - + // Vector == + bool operator==(const Vector3& right) + { + return ((x == right.x) && (y == right.y) && (z == right.z)); + } + // Vector != + bool operator!=(const Vector3& right) + { + return !((x == right.x) && (y == right.y) && (z == right.z)); + } // Length squared of vector float LengthSq() const { return (x*x + y*y + z*z); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -357,7 +309,6 @@ class Vector3 y /= length; z /= length; } - // Normalize the provided vector static Vector3 Normalize(const Vector3& vec) { @@ -365,13 +316,11 @@ class Vector3 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector3& a, const Vector3& b) { return (a.x * b.x + a.y * b.y + a.z * b.z); } - // Cross product between two vectors (a cross b) static Vector3 Cross(const Vector3& a, const Vector3& b) { @@ -381,23 +330,19 @@ class Vector3 temp.z = a.x * b.y - a.y * b.x; return temp; } - // Lerp from A to B by f static Vector3 Lerp(const Vector3& a, const Vector3& b, float f) { return Vector3(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector3 Reflect(const Vector3& v, const Vector3& n) { return v - 2.0f * Vector3::Dot(v, n) * n; } - static Vector3 Transform(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); // This will transform the vector and renormalize the w component static Vector3 TransformWithPerspDiv(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); - // Transform a Vector3 by a quaternion static Vector3 Transform(const Vector3& v, const class Quaternion& q); @@ -422,18 +367,15 @@ class Matrix3 { *this = Matrix3::Identity; } - explicit Matrix3(float inMat[3][3]) { memcpy(mat, inMat, 9 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication friend Matrix3 operator*(const Matrix3& left, const Matrix3& right) { @@ -443,49 +385,40 @@ class Matrix3 left.mat[0][0] * right.mat[0][0] + left.mat[0][1] * right.mat[1][0] + left.mat[0][2] * right.mat[2][0]; - retVal.mat[0][1] = left.mat[0][0] * right.mat[0][1] + left.mat[0][1] * right.mat[1][1] + left.mat[0][2] * right.mat[2][1]; - retVal.mat[0][2] = left.mat[0][0] * right.mat[0][2] + left.mat[0][1] * right.mat[1][2] + left.mat[0][2] * right.mat[2][2]; - // row 1 retVal.mat[1][0] = left.mat[1][0] * right.mat[0][0] + left.mat[1][1] * right.mat[1][0] + left.mat[1][2] * right.mat[2][0]; - retVal.mat[1][1] = left.mat[1][0] * right.mat[0][1] + left.mat[1][1] * right.mat[1][1] + left.mat[1][2] * right.mat[2][1]; - retVal.mat[1][2] = left.mat[1][0] * right.mat[0][2] + left.mat[1][1] * right.mat[1][2] + left.mat[1][2] * right.mat[2][2]; - // row 2 retVal.mat[2][0] = left.mat[2][0] * right.mat[0][0] + left.mat[2][1] * right.mat[1][0] + left.mat[2][2] * right.mat[2][0]; - retVal.mat[2][1] = left.mat[2][0] * right.mat[0][1] + left.mat[2][1] * right.mat[1][1] + left.mat[2][2] * right.mat[2][1]; - retVal.mat[2][2] = left.mat[2][0] * right.mat[0][2] + left.mat[2][1] * right.mat[1][2] + left.mat[2][2] * right.mat[2][2]; - return retVal; } @@ -556,18 +489,15 @@ class Matrix4 { *this = Matrix4::Identity; } - explicit Matrix4(float inMat[4][4]) { memcpy(mat, inMat, 16 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication (a * b) friend Matrix4 operator*(const Matrix4& a, const Matrix4& b) { @@ -578,136 +508,113 @@ class Matrix4 a.mat[0][1] * b.mat[1][0] + a.mat[0][2] * b.mat[2][0] + a.mat[0][3] * b.mat[3][0]; - retVal.mat[0][1] = a.mat[0][0] * b.mat[0][1] + a.mat[0][1] * b.mat[1][1] + a.mat[0][2] * b.mat[2][1] + a.mat[0][3] * b.mat[3][1]; - retVal.mat[0][2] = a.mat[0][0] * b.mat[0][2] + a.mat[0][1] * b.mat[1][2] + a.mat[0][2] * b.mat[2][2] + a.mat[0][3] * b.mat[3][2]; - retVal.mat[0][3] = a.mat[0][0] * b.mat[0][3] + a.mat[0][1] * b.mat[1][3] + a.mat[0][2] * b.mat[2][3] + a.mat[0][3] * b.mat[3][3]; - // row 1 retVal.mat[1][0] = a.mat[1][0] * b.mat[0][0] + a.mat[1][1] * b.mat[1][0] + a.mat[1][2] * b.mat[2][0] + a.mat[1][3] * b.mat[3][0]; - retVal.mat[1][1] = a.mat[1][0] * b.mat[0][1] + a.mat[1][1] * b.mat[1][1] + a.mat[1][2] * b.mat[2][1] + a.mat[1][3] * b.mat[3][1]; - retVal.mat[1][2] = a.mat[1][0] * b.mat[0][2] + a.mat[1][1] * b.mat[1][2] + a.mat[1][2] * b.mat[2][2] + a.mat[1][3] * b.mat[3][2]; - retVal.mat[1][3] = a.mat[1][0] * b.mat[0][3] + a.mat[1][1] * b.mat[1][3] + a.mat[1][2] * b.mat[2][3] + a.mat[1][3] * b.mat[3][3]; - // row 2 retVal.mat[2][0] = a.mat[2][0] * b.mat[0][0] + a.mat[2][1] * b.mat[1][0] + a.mat[2][2] * b.mat[2][0] + a.mat[2][3] * b.mat[3][0]; - retVal.mat[2][1] = a.mat[2][0] * b.mat[0][1] + a.mat[2][1] * b.mat[1][1] + a.mat[2][2] * b.mat[2][1] + a.mat[2][3] * b.mat[3][1]; - retVal.mat[2][2] = a.mat[2][0] * b.mat[0][2] + a.mat[2][1] * b.mat[1][2] + a.mat[2][2] * b.mat[2][2] + a.mat[2][3] * b.mat[3][2]; - retVal.mat[2][3] = a.mat[2][0] * b.mat[0][3] + a.mat[2][1] * b.mat[1][3] + a.mat[2][2] * b.mat[2][3] + a.mat[2][3] * b.mat[3][3]; - // row 3 retVal.mat[3][0] = a.mat[3][0] * b.mat[0][0] + a.mat[3][1] * b.mat[1][0] + a.mat[3][2] * b.mat[2][0] + a.mat[3][3] * b.mat[3][0]; - retVal.mat[3][1] = a.mat[3][0] * b.mat[0][1] + a.mat[3][1] * b.mat[1][1] + a.mat[3][2] * b.mat[2][1] + a.mat[3][3] * b.mat[3][1]; - retVal.mat[3][2] = a.mat[3][0] * b.mat[0][2] + a.mat[3][1] * b.mat[1][2] + a.mat[3][2] * b.mat[2][2] + a.mat[3][3] * b.mat[3][2]; - retVal.mat[3][3] = a.mat[3][0] * b.mat[0][3] + a.mat[3][1] * b.mat[1][3] + a.mat[3][2] * b.mat[2][3] + a.mat[3][3] * b.mat[3][3]; - return retVal; } - Matrix4& operator*=(const Matrix4& right) { *this = *this * right; return *this; } - // Invert the matrix - super slow void Invert(); - // Get the translation component of the matrix Vector3 GetTranslation() const { return Vector3(mat[3][0], mat[3][1], mat[3][2]); } - // Get the X axis of the matrix (forward) Vector3 GetXAxis() const { return Vector3::Normalize(Vector3(mat[0][0], mat[0][1], mat[0][2])); } - // Get the Y axis of the matrix (left) Vector3 GetYAxis() const { return Vector3::Normalize(Vector3(mat[1][0], mat[1][1], mat[1][2])); } - // Get the Z axis of the matrix (up) Vector3 GetZAxis() const { return Vector3::Normalize(Vector3(mat[2][0], mat[2][1], mat[2][2])); } - // Extract the scale component from the matrix Vector3 GetScale() const { @@ -717,7 +624,6 @@ class Matrix4 retVal.z = Vector3(mat[2][0], mat[2][1], mat[2][2]).Length(); return retVal; } - // Create a scale matrix with x, y, and z scales static Matrix4 CreateScale(float xScale, float yScale, float zScale) { @@ -730,18 +636,15 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateScale(const Vector3& scaleVector) { return CreateScale(scaleVector.x, scaleVector.y, scaleVector.z); } - // Create a scale matrix with a uniform factor static Matrix4 CreateScale(float scale) { return CreateScale(scale, scale, scale); } - // Rotation about x-axis static Matrix4 CreateRotationX(float theta) { @@ -754,7 +657,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about y-axis static Matrix4 CreateRotationY(float theta) { @@ -767,7 +669,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about z-axis static Matrix4 CreateRotationZ(float theta) { @@ -780,10 +681,8 @@ class Matrix4 }; return Matrix4(temp); } - // Create a rotation matrix from a quaternion static Matrix4 CreateFromQuaternion(const class Quaternion& q); - static Matrix4 CreateTranslation(const Vector3& trans) { float temp[4][4] = @@ -795,7 +694,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { Vector3 zaxis = Vector3::Normalize(target - eye); @@ -805,7 +703,6 @@ class Matrix4 trans.x = -Vector3::Dot(xaxis, eye); trans.y = -Vector3::Dot(yaxis, eye); trans.z = -Vector3::Dot(zaxis, eye); - float temp[4][4] = { { xaxis.x, yaxis.x, zaxis.x, 0.0f }, @@ -815,7 +712,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateOrtho(float width, float height, float near, float far) { float temp[4][4] = @@ -827,7 +723,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreatePerspectiveFOV(float fovY, float width, float height, float near, float far) { float yScale = Math::Cot(fovY / 2.0f); @@ -841,7 +736,6 @@ class Matrix4 }; return Matrix4(temp); } - // Create "Simple" View-Projection Matrix from Chapter 6 static Matrix4 CreateSimpleViewProj(float width, float height) { @@ -871,17 +765,13 @@ class Quaternion { *this = Quaternion::Identity; } - - // This directly sets the quaternion components -- - // don't use for axis/angle + // This directly sets the quaternion components -- don't use for axis/angle explicit Quaternion(float inX, float inY, float inZ, float inW) { Set(inX, inY, inZ, inW); } - - // Construct the quaternion from an axis and angle - // It is assumed that axis is already normalized, - // and the angle is in radians + /* Construct the quaternion from an axis and angle + NOTE: It is assumed that axis is already normalized, and the angle is in radians*/ explicit Quaternion(const Vector3& axis, float angle) { float scalar = Math::Sin(angle / 2.0f); @@ -890,7 +780,6 @@ class Quaternion z = axis.z * scalar; w = Math::Cos(angle / 2.0f); } - // Directly set the internal components void Set(float inX, float inY, float inZ, float inW) { @@ -899,24 +788,20 @@ class Quaternion z = inZ; w = inW; } - void Conjugate() { x *= -1.0f; y *= -1.0f; z *= -1.0f; } - float LengthSq() const { return (x*x + y*y + z*z + w*w); } - float Length() const { return Math::Sqrt(LengthSq()); } - void Normalize() { float length = Length(); @@ -925,7 +810,6 @@ class Quaternion z /= length; w /= length; } - // Normalize the provided quaternion static Quaternion Normalize(const Quaternion& q) { @@ -933,7 +817,6 @@ class Quaternion retVal.Normalize(); return retVal; } - // Linear interpolation static Quaternion Lerp(const Quaternion& a, const Quaternion& b, float f) { @@ -945,25 +828,20 @@ class Quaternion retVal.Normalize(); return retVal; } - static float Dot(const Quaternion& a, const Quaternion& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } - // Spherical Linear Interpolation static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float f) { float rawCosm = Quaternion::Dot(a, b); - float cosom = -rawCosm; if (rawCosm >= 0.0f) { cosom = rawCosm; } - float scale0, scale1; - if (cosom < 0.9999f) { const float omega = Math::Acos(cosom); @@ -973,17 +851,14 @@ class Quaternion } else { - // Use linear interpolation if the quaternions - // are collinear + // Use linear interpolation if the quaternions are collinear scale0 = 1.0f - f; scale1 = f; } - if (rawCosm < 0.0f) { scale1 = -scale1; } - Quaternion retVal; retVal.x = scale0 * a.x + scale1 * b.x; retVal.y = scale0 * a.y + scale1 * b.y; @@ -992,13 +867,11 @@ class Quaternion retVal.Normalize(); return retVal; } - // Concatenate // Rotate by q FOLLOWED BY p static Quaternion Concatenate(const Quaternion& q, const Quaternion& p) { Quaternion retVal; - // Vector component is: // ps * qv + qs * pv + pv x qv Vector3 qv(q.x, q.y, q.z); @@ -1007,11 +880,9 @@ class Quaternion retVal.x = newVec.x; retVal.y = newVec.y; retVal.z = newVec.z; - // Scalar component is: // ps * qs - pv . qv retVal.w = p.w * q.w - Vector3::Dot(pv, qv); - return retVal; } @@ -1030,4 +901,4 @@ namespace Color static const Vector3 LightBlue(0.68f, 0.85f, 0.9f); static const Vector3 LightPink(1.0f, 0.71f, 0.76f); static const Vector3 LightGreen(0.56f, 0.93f, 0.56f); -} +} \ No newline at end of file diff --git a/Chapter05/MoveComponent.cpp b/Chapter05/MoveComponent.cpp index c1a5d5b2..07cc854b 100644 --- a/Chapter05/MoveComponent.cpp +++ b/Chapter05/MoveComponent.cpp @@ -9,33 +9,28 @@ #include "MoveComponent.h" #include "Actor.h" -MoveComponent::MoveComponent(class Actor* owner, int updateOrder) -:Component(owner, updateOrder) -,mAngularSpeed(0.0f) -,mForwardSpeed(0.0f) +MoveComponent::MoveComponent(class Actor* owner, int updateOrder): Component(owner, updateOrder), mAngularSpeed(0.0f), mForwardSpeed(0.0f) { - } void MoveComponent::Update(float deltaTime) { if (!Math::NearZero(mAngularSpeed)) { - float rot = mOwner->GetRotation(); + float rot = pOwner->GetRotation(); rot += mAngularSpeed * deltaTime; - mOwner->SetRotation(rot); + pOwner->SetRotation(rot); } - if (!Math::NearZero(mForwardSpeed)) { - Vector2 pos = mOwner->GetPosition(); - pos += mOwner->GetForward() * mForwardSpeed * deltaTime; + Vector2 pos = pOwner->GetPosition(); + pos += pOwner->GetForward() * mForwardSpeed * deltaTime; // Screen wrapping (for asteroids) if (pos.x < -512.0f) { pos.x = 510.0f; } else if (pos.x > 512.0f) { pos.x = -510.0f; } if (pos.y < -384.0f) { pos.y = 382.0f; } else if (pos.y > 384.0f) { pos.y = -382.0f; } - mOwner->SetPosition(pos); + pOwner->SetPosition(pos); } -} +} \ No newline at end of file diff --git a/Chapter05/MoveComponent.h b/Chapter05/MoveComponent.h index def7d389..c737e66b 100644 --- a/Chapter05/MoveComponent.h +++ b/Chapter05/MoveComponent.h @@ -9,13 +9,12 @@ #pragma once #include "Component.h" -class MoveComponent : public Component +class MoveComponent: public Component { public: // Lower update order to update first MoveComponent(class Actor* owner, int updateOrder = 10); void Update(float deltaTime) override; - float GetAngularSpeed() const { return mAngularSpeed; } float GetForwardSpeed() const { return mForwardSpeed; } void SetAngularSpeed(float speed) { mAngularSpeed = speed; } @@ -23,4 +22,4 @@ class MoveComponent : public Component private: float mAngularSpeed; float mForwardSpeed; -}; +}; \ No newline at end of file diff --git a/Chapter05/Random.cpp b/Chapter05/Random.cpp index 05a3a32a..df2da134 100644 --- a/Chapter05/Random.cpp +++ b/Chapter05/Random.cpp @@ -48,4 +48,4 @@ Vector3 Random::GetVector(const Vector3& min, const Vector3& max) return min + (max - min) * r; } -std::mt19937 Random::sGenerator; +std::mt19937 Random::sGenerator; \ No newline at end of file diff --git a/Chapter05/Random.h b/Chapter05/Random.h index 3ae92fe5..cd216013 100644 --- a/Chapter05/Random.h +++ b/Chapter05/Random.h @@ -14,23 +14,18 @@ class Random { public: static void Init(); - // Seed the generator with the specified int // NOTE: You should generally not need to manually use this static void Seed(unsigned int seed); - // Get a float between 0.0f and 1.0f static float GetFloat(); - // Get a float from the specified range static float GetFloatRange(float min, float max); - // Get an int from the specified range static int GetIntRange(int min, int max); - // Get a random vector given the min/max bounds static Vector2 GetVector(const Vector2& min, const Vector2& max); static Vector3 GetVector(const Vector3& min, const Vector3& max); private: static std::mt19937 sGenerator; -}; +}; \ No newline at end of file diff --git a/Chapter05/Shader.cpp b/Chapter05/Shader.cpp index e32c07a2..ba8e5435 100644 --- a/Chapter05/Shader.cpp +++ b/Chapter05/Shader.cpp @@ -12,46 +12,28 @@ #include #include -Shader::Shader() - : mShaderProgram(0) - , mVertexShader(0) - , mFragShader(0) +Shader::Shader(): mShaderProgram(0), mVertexShader(0), mFragShader(0) { - } Shader::~Shader() { - } bool Shader::Load(const std::string& vertName, const std::string& fragName) { // Compile vertex and pixel shaders - if (!CompileShader(vertName, - GL_VERTEX_SHADER, - mVertexShader) || - !CompileShader(fragName, - GL_FRAGMENT_SHADER, - mFragShader)) + if (!CompileShader(vertName, GL_VERTEX_SHADER, mVertexShader) || !CompileShader(fragName, GL_FRAGMENT_SHADER, mFragShader)) { return false; } - - // Now create a shader program that - // links together the vertex/frag shaders + // Now create a shader program that links together the vertex/frag shaders mShaderProgram = glCreateProgram(); glAttachShader(mShaderProgram, mVertexShader); glAttachShader(mShaderProgram, mFragShader); glLinkProgram(mShaderProgram); - // Verify that the program linked successfully - if (!IsValidProgram()) - { - return false; - } - - return true; + return IsValidProgram(); } void Shader::Unload() @@ -76,9 +58,7 @@ void Shader::SetMatrixUniform(const char* name, const Matrix4& matrix) glUniformMatrix4fv(loc, 1, GL_TRUE, matrix.GetAsFloatPtr()); } -bool Shader::CompileShader(const std::string& fileName, - GLenum shaderType, - GLuint& outShader) +bool Shader::CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader) { // Open file std::ifstream shaderFile(fileName); @@ -89,13 +69,11 @@ bool Shader::CompileShader(const std::string& fileName, sstream << shaderFile.rdbuf(); std::string contents = sstream.str(); const char* contentsChar = contents.c_str(); - // Create a shader of the specified type outShader = glCreateShader(shaderType); // Set the source characters and try to compile glShaderSource(outShader, 1, &(contentsChar), nullptr); glCompileShader(outShader); - if (!IsCompiled(outShader)) { SDL_Log("Failed to compile shader %s", fileName.c_str()); @@ -107,7 +85,6 @@ bool Shader::CompileShader(const std::string& fileName, SDL_Log("Shader file not found: %s", fileName.c_str()); return false; } - return true; } @@ -116,7 +93,6 @@ bool Shader::IsCompiled(GLuint shader) GLint status; // Query the compile status glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { char buffer[512]; @@ -125,13 +101,11 @@ bool Shader::IsCompiled(GLuint shader) SDL_Log("GLSL Compile Failed:\n%s", buffer); return false; } - return true; } bool Shader::IsValidProgram() { - GLint status; // Query the link status glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &status); @@ -143,6 +117,5 @@ bool Shader::IsValidProgram() SDL_Log("GLSL Link Status:\n%s", buffer); return false; } - return true; -} +} \ No newline at end of file diff --git a/Chapter05/Shader.h b/Chapter05/Shader.h index 2b0161c0..445951d6 100644 --- a/Chapter05/Shader.h +++ b/Chapter05/Shader.h @@ -25,10 +25,7 @@ class Shader void SetMatrixUniform(const char* name, const Matrix4& matrix); private: // Tries to compile the specified shader - bool CompileShader(const std::string& fileName, - GLenum shaderType, - GLuint& outShader); - + bool CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader); // Tests whether shader compiled successfully bool IsCompiled(GLuint shader); // Tests whether vertex/fragment programs link @@ -38,4 +35,4 @@ class Shader GLuint mVertexShader; GLuint mFragShader; GLuint mShaderProgram; -}; +}; \ No newline at end of file diff --git a/Chapter05/Shaders/Basic.frag b/Chapter05/Shaders/Basic.frag index af9a33e5..ab3ab9b0 100644 --- a/Chapter05/Shaders/Basic.frag +++ b/Chapter05/Shaders/Basic.frag @@ -9,12 +9,11 @@ // Request GLSL 3.3 #version 330 -// This corresponds to the output color -// to the color buffer +// This corresponds to the output color to the color buffer out vec4 outColor; void main() { // RGBA of 100% blue, 100% opaque outColor = vec4(0.0, 0.0, 1.0, 1.0); -} +} \ No newline at end of file diff --git a/Chapter05/Shaders/Basic.vert b/Chapter05/Shaders/Basic.vert index 345b3c05..4c62a33f 100644 --- a/Chapter05/Shaders/Basic.vert +++ b/Chapter05/Shaders/Basic.vert @@ -20,4 +20,4 @@ void main() // coordinate. // For now set the 4th coordinate to 1.0 gl_Position = vec4(inPosition, 1.0); -} +} \ No newline at end of file diff --git a/Chapter05/Shaders/Sprite.frag b/Chapter05/Shaders/Sprite.frag index f48caf3d..bc8f5f9c 100644 --- a/Chapter05/Shaders/Sprite.frag +++ b/Chapter05/Shaders/Sprite.frag @@ -11,10 +11,8 @@ // Tex coord input from vertex shader in vec2 fragTexCoord; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; @@ -22,4 +20,4 @@ void main() { // Sample color from texture outColor = texture(uTexture, fragTexCoord); -} +} \ No newline at end of file diff --git a/Chapter05/Shaders/Sprite.vert b/Chapter05/Shaders/Sprite.vert index ea0f396f..526b5de7 100644 --- a/Chapter05/Shaders/Sprite.vert +++ b/Chapter05/Shaders/Sprite.vert @@ -12,11 +12,9 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec2 inTexCoord; - // Add texture coordinate as output out vec2 fragTexCoord; @@ -30,4 +28,4 @@ void main() // Transform // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter05/Shaders/Transform.vert b/Chapter05/Shaders/Transform.vert index fc59d32e..7f38dd4f 100644 --- a/Chapter05/Shaders/Transform.vert +++ b/Chapter05/Shaders/Transform.vert @@ -12,7 +12,6 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Vertex attributes in vec3 inPosition; @@ -20,4 +19,4 @@ void main() { vec4 pos = vec4(inPosition, 1.0); gl_Position = pos * uWorldTransform * uViewProj; -} +} \ No newline at end of file diff --git a/Chapter05/Ship.cpp b/Chapter05/Ship.cpp index e5b236db..a3772380 100644 --- a/Chapter05/Ship.cpp +++ b/Chapter05/Ship.cpp @@ -12,14 +12,11 @@ #include "Game.h" #include "Laser.h" -Ship::Ship(Game* game) - :Actor(game) - ,mLaserCooldown(0.0f) +Ship::Ship(Game* game): Actor(game), mLaserCooldown(0.0f) { // Create a sprite component SpriteComponent* sc = new SpriteComponent(this, 150); sc->SetTexture(game->GetTexture("Assets/Ship.png")); - // Create an input component and set keys/speed InputComponent* ic = new InputComponent(this); ic->SetForwardKey(SDL_SCANCODE_W); @@ -43,8 +40,7 @@ void Ship::ActorInput(const uint8_t* keyState) Laser* laser = new Laser(GetGame()); laser->SetPosition(GetPosition()); laser->SetRotation(GetRotation()); - // Reset laser cooldown (half second) mLaserCooldown = 0.5f; } -} +} \ No newline at end of file diff --git a/Chapter05/Ship.h b/Chapter05/Ship.h index 808639ff..9ac4a6f2 100644 --- a/Chapter05/Ship.h +++ b/Chapter05/Ship.h @@ -8,11 +8,10 @@ #pragma once #include "Actor.h" -class Ship : public Actor +class Ship: public Actor { public: Ship(class Game* game); - void UpdateActor(float deltaTime) override; void ActorInput(const uint8_t* keyState) override; private: diff --git a/Chapter05/SpriteComponent.cpp b/Chapter05/SpriteComponent.cpp index d62b9840..57127170 100644 --- a/Chapter05/SpriteComponent.cpp +++ b/Chapter05/SpriteComponent.cpp @@ -12,40 +12,28 @@ #include "Actor.h" #include "Game.h" -SpriteComponent::SpriteComponent(Actor* owner, int drawOrder) - :Component(owner) - ,mTexture(nullptr) - ,mDrawOrder(drawOrder) - ,mTexWidth(0) - ,mTexHeight(0) +SpriteComponent::SpriteComponent(Actor* owner, int drawOrder): Component(owner), pTexture(nullptr), mDrawOrder(drawOrder), mTexWidth(0), mTexHeight(0) { - mOwner->GetGame()->AddSprite(this); + pOwner->GetGame()->AddSprite(this); } SpriteComponent::~SpriteComponent() { - mOwner->GetGame()->RemoveSprite(this); + pOwner->GetGame()->RemoveSprite(this); } void SpriteComponent::Draw(Shader* shader) { - if (mTexture) + if (pTexture) { // Scale the quad by the width/height of texture - Matrix4 scaleMat = Matrix4::CreateScale( - static_cast(mTexWidth), - static_cast(mTexHeight), - 1.0f); - - Matrix4 world = scaleMat * mOwner->GetWorldTransform(); - - // Since all sprites use the same shader/vertices, - // the game first sets them active before any sprite draws - + Matrix4 scaleMat = Matrix4::CreateScale(static_cast(mTexWidth), static_cast(mTexHeight), 1.0f); + Matrix4 world = scaleMat * pOwner->GetWorldTransform(); + // NOTE: Since all sprites use the same shader/vertices, the game first sets them active before any sprite draws // Set world transform shader->SetMatrixUniform("uWorldTransform", world); // Set current texture - mTexture->SetActive(); + pTexture->SetActive(); // Draw quad glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); } @@ -53,8 +41,8 @@ void SpriteComponent::Draw(Shader* shader) void SpriteComponent::SetTexture(Texture* texture) { - mTexture = texture; + pTexture = texture; // Set width/height mTexWidth = texture->GetWidth(); mTexHeight = texture->GetHeight(); -} +} \ No newline at end of file diff --git a/Chapter05/SpriteComponent.h b/Chapter05/SpriteComponent.h index 6c5642f2..581cb883 100644 --- a/Chapter05/SpriteComponent.h +++ b/Chapter05/SpriteComponent.h @@ -9,22 +9,20 @@ #pragma once #include "Component.h" #include "SDL/SDL.h" -class SpriteComponent : public Component +class SpriteComponent: public Component { public: // (Lower draw order corresponds with further back) SpriteComponent(class Actor* owner, int drawOrder = 100); ~SpriteComponent(); - virtual void Draw(class Shader* shader); virtual void SetTexture(class Texture* texture); - int GetDrawOrder() const { return mDrawOrder; } int GetTexHeight() const { return mTexHeight; } int GetTexWidth() const { return mTexWidth; } protected: - class Texture* mTexture; + class Texture* pTexture; int mDrawOrder; int mTexWidth; int mTexHeight; -}; +}; \ No newline at end of file diff --git a/Chapter05/Texture.cpp b/Chapter05/Texture.cpp index 7d0dbd3e..a25c7d52 100644 --- a/Chapter05/Texture.cpp +++ b/Chapter05/Texture.cpp @@ -11,50 +11,35 @@ #include #include -Texture::Texture() -:mTextureID(0) -,mWidth(0) -,mHeight(0) +Texture::Texture(): mTextureID(0), mWidth(0), mHeight(0) { - } Texture::~Texture() { - } bool Texture::Load(const std::string& fileName) { int channels = 0; - - unsigned char* image = SOIL_load_image(fileName.c_str(), - &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); - + unsigned char* image = SOIL_load_image(fileName.c_str(), &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); if (image == nullptr) { SDL_Log("SOIL failed to load image %s: %s", fileName.c_str(), SOIL_last_result()); return false; } - int format = GL_RGB; if (channels == 4) { format = GL_RGBA; } - glGenTextures(1, &mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID); - - glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, - GL_UNSIGNED_BYTE, image); - + glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, GL_UNSIGNED_BYTE, image); SOIL_free_image_data(image); - // Enable bilinear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - return true; } @@ -66,4 +51,4 @@ void Texture::Unload() void Texture::SetActive() { glBindTexture(GL_TEXTURE_2D, mTextureID); -} +} \ No newline at end of file diff --git a/Chapter05/Texture.h b/Chapter05/Texture.h index ed12b0dc..b745ffac 100644 --- a/Chapter05/Texture.h +++ b/Chapter05/Texture.h @@ -13,12 +13,9 @@ class Texture public: Texture(); ~Texture(); - bool Load(const std::string& fileName); void Unload(); - void SetActive(); - int GetWidth() const { return mWidth; } int GetHeight() const { return mHeight; } private: @@ -27,4 +24,4 @@ class Texture // Width/height of the texture int mWidth; int mHeight; -}; +}; \ No newline at end of file diff --git a/Chapter05/VertexArray.cpp b/Chapter05/VertexArray.cpp index c7bff446..4c6be7eb 100644 --- a/Chapter05/VertexArray.cpp +++ b/Chapter05/VertexArray.cpp @@ -9,33 +9,25 @@ #include "VertexArray.h" #include -VertexArray::VertexArray(const float* verts, unsigned int numVerts, - const unsigned int* indices, unsigned int numIndices) - :mNumVerts(numVerts) - ,mNumIndices(numIndices) +VertexArray::VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices): mNumVerts(numVerts), mNumIndices(numIndices) { // Create vertex array glGenVertexArrays(1, &mVertexArray); glBindVertexArray(mVertexArray); - // Create vertex buffer glGenBuffers(1, &mVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); glBufferData(GL_ARRAY_BUFFER, numVerts * 5 * sizeof(float), verts, GL_STATIC_DRAW); - // Create index buffer glGenBuffers(1, &mIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned int), indices, GL_STATIC_DRAW); - - // Specify the vertex attributes - // (For now, assume one vertex format) - // Position is 3 floats starting at offset 0 + /* Specify the vertex attributes (For now, assume one vertex format) + NOTE: Position is 3 floats starting at offset 0*/ glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, - reinterpret_cast(sizeof(float) * 3)); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, reinterpret_cast(sizeof(float) * 3)); } VertexArray::~VertexArray() @@ -48,4 +40,4 @@ VertexArray::~VertexArray() void VertexArray::SetActive() { glBindVertexArray(mVertexArray); -} +} \ No newline at end of file diff --git a/Chapter05/VertexArray.h b/Chapter05/VertexArray.h index 9f2c3e9b..7540d847 100644 --- a/Chapter05/VertexArray.h +++ b/Chapter05/VertexArray.h @@ -10,13 +10,10 @@ class VertexArray { public: - VertexArray(const float* verts, unsigned int numVerts, - const unsigned int* indices, unsigned int numIndices); + VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices); ~VertexArray(); - // Activate this vertex array (so we can draw it) void SetActive(); - unsigned int GetNumIndices() const { return mNumIndices; } unsigned int GetNumVerts() const { return mNumVerts; } private: diff --git a/TODO.txt b/TODO.txt index 0990299d..a608fb3f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,4 @@ TODO: -5.1 - Updating exercise 5.2 - Add vertex color (RGB) to sprite shader 6.1 - Multiple mesh shaders 6.2 - Point lights @@ -32,4 +31,5 @@ Skipped: 3.3 - 2D stuff 4.2 - I do not care about Connect 4 Done: -4.1 - State Machine \ No newline at end of file +4.1 - State Machine +5.1 - Updating exercise \ No newline at end of file From e75f5e019cf7b1a979b9966cad90b34d2f4dba2e Mon Sep 17 00:00:00 2001 From: bobnone Date: Wed, 18 May 2022 17:35:01 -0500 Subject: [PATCH 3/6] Finished 5.2 --- Chapter05/Game.cpp | 11 ++++++----- Chapter05/Shaders/Sprite.frag | 7 ++++++- Chapter05/Shaders/Sprite.vert | 6 +++++- Chapter05/VertexArray.cpp | 13 +++++++++---- Chapter05/VertexArray.h | 2 +- TODO.txt | 6 +++--- 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Chapter05/Game.cpp b/Chapter05/Game.cpp index f7ea6e7e..57cf7e5b 100644 --- a/Chapter05/Game.cpp +++ b/Chapter05/Game.cpp @@ -203,17 +203,18 @@ bool Game::LoadShaders() void Game::CreateSpriteVerts() { + // Position (3), Texture coordinates(2), Vertex color(3) float vertices[] = { - -0.5f, 0.5f, 0.f, 0.f, 0.f, // top left - 0.5f, 0.5f, 0.f, 1.f, 0.f, // top right - 0.5f, -0.5f, 0.f, 1.f, 1.f, // bottom right - -0.5f, -0.5f, 0.f, 0.f, 1.f // bottom left + -0.5f, 0.5f, 0.f, 0.f, 0.f, 1.0f, 0.0f, 0.0f, // top left + 0.5f, 0.5f, 0.f, 1.f, 0.f, 0.0f, 1.0f, 0.0f, // top right + 0.5f, -0.5f, 0.f, 1.f, 1.f, 1.0f, 1.0f, 0.0f, // bottom right + -0.5f, -0.5f, 0.f, 0.f, 1.f, 0.0f, 1.0f, 1.0f, // bottom left }; unsigned int indices[] = { 0, 1, 2, 2, 3, 0 }; - pSpriteVerts = new VertexArray(vertices, 4, indices, 6); + pSpriteVerts = new VertexArray(vertices, 8, 4, indices, 6); } void Game::LoadData() diff --git a/Chapter05/Shaders/Sprite.frag b/Chapter05/Shaders/Sprite.frag index bc8f5f9c..215f65f9 100644 --- a/Chapter05/Shaders/Sprite.frag +++ b/Chapter05/Shaders/Sprite.frag @@ -11,6 +11,8 @@ // Tex coord input from vertex shader in vec2 fragTexCoord; +// Vertex color +in vec3 vertexColor; // This corresponds to the output color to the color buffer out vec4 outColor; // This is used for the texture sampling @@ -19,5 +21,8 @@ uniform sampler2D uTexture; void main() { // Sample color from texture - outColor = texture(uTexture, fragTexCoord); + float x = (texture(uTexture, fragTexCoord).x * vertexColor.x)/2; + float y = (texture(uTexture, fragTexCoord).y * vertexColor.y)/2; + float z = (texture(uTexture, fragTexCoord).z * vertexColor.z)/2; + outColor = vec4(x, y, z, texture(uTexture, fragTexCoord).w); } \ No newline at end of file diff --git a/Chapter05/Shaders/Sprite.vert b/Chapter05/Shaders/Sprite.vert index 526b5de7..0e9e1c3b 100644 --- a/Chapter05/Shaders/Sprite.vert +++ b/Chapter05/Shaders/Sprite.vert @@ -15,8 +15,11 @@ uniform mat4 uViewProj; // Attribute 0 is position, 1 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec2 inTexCoord; +layout(location = 2) in vec3 inVertColor; // Add texture coordinate as output out vec2 fragTexCoord; +// Add vertex color as output +out vec3 vertexColor; void main() { @@ -24,8 +27,9 @@ void main() vec4 pos = vec4(inPosition, 1.0); // Transform position to world space, then clip space gl_Position = pos * uWorldTransform * uViewProj; - // Transform // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; + // Pass along the vertex color to frag shader + vertexColor = inVertColor; } \ No newline at end of file diff --git a/Chapter05/VertexArray.cpp b/Chapter05/VertexArray.cpp index 4c6be7eb..3b596c1e 100644 --- a/Chapter05/VertexArray.cpp +++ b/Chapter05/VertexArray.cpp @@ -9,7 +9,7 @@ #include "VertexArray.h" #include -VertexArray::VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices): mNumVerts(numVerts), mNumIndices(numIndices) +VertexArray::VertexArray(const float* verts, const int size, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices): mNumVerts(numVerts), mNumIndices(numIndices) { // Create vertex array glGenVertexArrays(1, &mVertexArray); @@ -17,7 +17,7 @@ VertexArray::VertexArray(const float* verts, unsigned int numVerts, const unsign // Create vertex buffer glGenBuffers(1, &mVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); - glBufferData(GL_ARRAY_BUFFER, numVerts * 5 * sizeof(float), verts, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, numVerts * size * sizeof(float), verts, GL_STATIC_DRAW); // Create index buffer glGenBuffers(1, &mIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); @@ -25,9 +25,14 @@ VertexArray::VertexArray(const float* verts, unsigned int numVerts, const unsign /* Specify the vertex attributes (For now, assume one vertex format) NOTE: Position is 3 floats starting at offset 0*/ glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * size, 0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, reinterpret_cast(sizeof(float) * 3)); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * size, reinterpret_cast(sizeof(float) * 3)); + // Tell OpenGl we want to create a new Attribute ID=2 + glEnableVertexAttribArray(2); + // Tell OpenGL we want to create a Vecter3 of floats + // NOTE: ID, vector size, type, IDK, total size, starting index + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * size, reinterpret_cast(sizeof(float) * 5)); } VertexArray::~VertexArray() diff --git a/Chapter05/VertexArray.h b/Chapter05/VertexArray.h index 7540d847..6a5e59c9 100644 --- a/Chapter05/VertexArray.h +++ b/Chapter05/VertexArray.h @@ -10,7 +10,7 @@ class VertexArray { public: - VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices); + VertexArray(const float* verts, const int size, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices); ~VertexArray(); // Activate this vertex array (so we can draw it) void SetActive(); diff --git a/TODO.txt b/TODO.txt index a608fb3f..1dd235e5 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,4 @@ TODO: -5.2 - Add vertex color (RGB) to sprite shader 6.1 - Multiple mesh shaders 6.2 - Point lights 7.1 - Add velocity to the listener @@ -22,7 +21,7 @@ TODO: 14.2 - Create binary for animations Skipped: 1.1 - I do not care about Pong -1.2 - More Pong +1.2 - I do not care about Pong 2.1 - Theory stuff 2.2 - 2D stuff 2.3 - 2D stuff @@ -32,4 +31,5 @@ Skipped: 4.2 - I do not care about Connect 4 Done: 4.1 - State Machine -5.1 - Updating exercise \ No newline at end of file +5.1 - Updating exercise +5.2 - Add vertex color (RGB) to sprite shader \ No newline at end of file From 9384c8383fee211217f3bded8ebf5ab11e56479d Mon Sep 17 00:00:00 2001 From: bobnone Date: Fri, 20 May 2022 01:28:06 -0500 Subject: [PATCH 4/6] Finished 6.1 --- Chapter06/Actor.cpp | 27 ++--- Chapter06/Actor.h | 18 +--- Chapter06/Assets/Cube.gpmesh | 2 +- Chapter06/Assets/Sphere.gpmesh | 2 +- Chapter06/CameraActor.cpp | 14 +-- Chapter06/CameraActor.h | 7 +- Chapter06/CircleComponent.cpp | 13 +-- Chapter06/CircleComponent.h | 6 +- Chapter06/Component.cpp | 10 +- Chapter06/Component.h | 7 +- Chapter06/Game.cpp | 82 +++++---------- Chapter06/Game.h | 14 +-- Chapter06/Game.vcxproj | 6 +- Chapter06/Main.cpp | 2 +- Chapter06/Math.cpp | 23 +---- Chapter06/Math.h | 155 ++--------------------------- Chapter06/Mesh.cpp | 28 +----- Chapter06/MeshComponent.cpp | 15 +-- Chapter06/MeshComponent.h | 9 +- Chapter06/MoveComponent.cpp | 19 ++-- Chapter06/MoveComponent.h | 5 +- Chapter06/PlaneActor.cpp | 8 +- Chapter06/PlaneActor.h | 2 +- Chapter06/Renderer.cpp | 166 ++++++++++++++++++------------- Chapter06/Renderer.h | 39 +++----- Chapter06/Shader.cpp | 30 +----- Chapter06/Shader.h | 7 +- Chapter06/Shaders/BasicMesh.frag | 4 +- Chapter06/Shaders/BasicMesh.vert | 5 +- Chapter06/Shaders/Phong.frag | 9 +- Chapter06/Shaders/Phong.vert | 6 +- Chapter06/Shaders/Sprite.frag | 4 +- Chapter06/Shaders/Sprite.vert | 5 +- Chapter06/SpriteComponent.cpp | 29 ++---- Chapter06/SpriteComponent.h | 8 +- Chapter06/Texture.cpp | 23 +---- Chapter06/Texture.h | 5 +- Chapter06/VertexArray.cpp | 16 +-- Chapter06/VertexArray.h | 4 +- 39 files changed, 247 insertions(+), 587 deletions(-) diff --git a/Chapter06/Actor.cpp b/Chapter06/Actor.cpp index b3715cca..321fc7ca 100644 --- a/Chapter06/Actor.cpp +++ b/Chapter06/Actor.cpp @@ -11,20 +11,14 @@ #include "Component.h" #include -Actor::Actor(Game* game) - :mState(EActive) - ,mPosition(Vector3::Zero) - ,mRotation(Quaternion::Identity) - ,mScale(1.0f) - ,mGame(game) - ,mRecomputeWorldTransform(true) +Actor::Actor(Game* game): mState(EActive), mPosition(Vector3::Zero), mRotation(Quaternion::Identity), mScale(1.0f), pGame(game), mRecomputeWorldTransform(true) { - mGame->AddActor(this); + pGame->AddActor(this); } Actor::~Actor() { - mGame->RemoveActor(this); + pGame->RemoveActor(this); // Need to delete components // Because ~Component calls RemoveComponent, need a different style loop while (!mComponents.empty()) @@ -38,17 +32,15 @@ void Actor::Update(float deltaTime) if (mState == EActive) { ComputeWorldTransform(); - UpdateComponents(deltaTime); UpdateActor(deltaTime); - ComputeWorldTransform(); } } void Actor::UpdateComponents(float deltaTime) { - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->Update(deltaTime); } @@ -63,11 +55,10 @@ void Actor::ProcessInput(const uint8_t* keyState) if (mState == EActive) { // First process input for components - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->ProcessInput(keyState); } - ActorInput(keyState); } } @@ -85,7 +76,6 @@ void Actor::ComputeWorldTransform() mWorldTransform = Matrix4::CreateScale(mScale); mWorldTransform *= Matrix4::CreateFromQuaternion(mRotation); mWorldTransform *= Matrix4::CreateTranslation(mPosition); - // Inform components world transform updated for (auto comp : mComponents) { @@ -100,16 +90,13 @@ void Actor::AddComponent(Component* component) // (The first element with a order higher than me) int myOrder = component->GetUpdateOrder(); auto iter = mComponents.begin(); - for (; - iter != mComponents.end(); - ++iter) + for (; iter != mComponents.end(); ++iter) { if (myOrder < (*iter)->GetUpdateOrder()) { break; } } - // Inserts element before position of iterator mComponents.insert(iter, component); } @@ -121,4 +108,4 @@ void Actor::RemoveComponent(Component* component) { mComponents.erase(iter); } -} +} \ No newline at end of file diff --git a/Chapter06/Actor.h b/Chapter06/Actor.h index 05d6b1b6..59421c32 100644 --- a/Chapter06/Actor.h +++ b/Chapter06/Actor.h @@ -20,22 +20,18 @@ class Actor EPaused, EDead }; - Actor(class Game* game); virtual ~Actor(); - // Update function called from Game (not overridable) void Update(float deltaTime); // Updates all the components attached to the actor (not overridable) void UpdateComponents(float deltaTime); // Any actor-specific update code (overridable) virtual void UpdateActor(float deltaTime); - // ProcessInput function called from Game (not overridable) void ProcessInput(const uint8_t* keyState); // Any actor-specific input code (overridable) virtual void ActorInput(const uint8_t* keyState); - // Getters/setters const Vector3& GetPosition() const { return mPosition; } void SetPosition(const Vector3& pos) { mPosition = pos; mRecomputeWorldTransform = true; } @@ -43,32 +39,24 @@ class Actor void SetScale(float scale) { mScale = scale; mRecomputeWorldTransform = true; } const Quaternion& GetRotation() const { return mRotation; } void SetRotation(const Quaternion& rotation) { mRotation = rotation; mRecomputeWorldTransform = true; } - void ComputeWorldTransform(); const Matrix4& GetWorldTransform() const { return mWorldTransform; } - Vector3 GetForward() const { return Vector3::Transform(Vector3::UnitX, mRotation); } - State GetState() const { return mState; } void SetState(State state) { mState = state; } - - class Game* GetGame() { return mGame; } - - + class Game* GetGame() { return pGame; } // Add/remove components void AddComponent(class Component* component); void RemoveComponent(class Component* component); private: // Actor's state State mState; - // Transform Matrix4 mWorldTransform; Vector3 mPosition; Quaternion mRotation; float mScale; bool mRecomputeWorldTransform; - std::vector mComponents; - class Game* mGame; -}; + class Game* pGame; +}; \ No newline at end of file diff --git a/Chapter06/Assets/Cube.gpmesh b/Chapter06/Assets/Cube.gpmesh index 408d9061..99a347da 100644 --- a/Chapter06/Assets/Cube.gpmesh +++ b/Chapter06/Assets/Cube.gpmesh @@ -1,7 +1,7 @@ { "version":1, "vertexformat":"PosNormTex", - "shader":"BasicMesh", + "shader":"Phong", "textures":[ "Assets/Cube.png" ], diff --git a/Chapter06/Assets/Sphere.gpmesh b/Chapter06/Assets/Sphere.gpmesh index 82ed952c..51b46a4c 100644 --- a/Chapter06/Assets/Sphere.gpmesh +++ b/Chapter06/Assets/Sphere.gpmesh @@ -1,7 +1,7 @@ { "version":1, "vertexformat":"PosNormTex", - "shader":"BasicMesh", + "shader":"Phong", "textures":[ "Assets/Sphere.png" ], diff --git a/Chapter06/CameraActor.cpp b/Chapter06/CameraActor.cpp index 5338b1bf..af63bf7f 100644 --- a/Chapter06/CameraActor.cpp +++ b/Chapter06/CameraActor.cpp @@ -12,21 +12,18 @@ #include "Renderer.h" #include "Game.h" -CameraActor::CameraActor(Game* game) - :Actor(game) +CameraActor::CameraActor(Game* game): Actor(game) { - mMoveComp = new MoveComponent(this); + pMoveComp = new MoveComponent(this); } void CameraActor::UpdateActor(float deltaTime) { Actor::UpdateActor(deltaTime); - // Compute new camera from this actor Vector3 cameraPos = GetPosition(); Vector3 target = GetPosition() + GetForward() * 100.0f; Vector3 up = Vector3::UnitZ; - Matrix4 view = Matrix4::CreateLookAt(cameraPos, target, up); GetGame()->GetRenderer()->SetViewMatrix(view); } @@ -52,7 +49,6 @@ void CameraActor::ActorInput(const uint8_t* keys) { angularSpeed += Math::TwoPi; } - - mMoveComp->SetForwardSpeed(forwardSpeed); - mMoveComp->SetAngularSpeed(angularSpeed); -} + pMoveComp->SetForwardSpeed(forwardSpeed); + pMoveComp->SetAngularSpeed(angularSpeed); +} \ No newline at end of file diff --git a/Chapter06/CameraActor.h b/Chapter06/CameraActor.h index a7e3923c..bfc5df36 100644 --- a/Chapter06/CameraActor.h +++ b/Chapter06/CameraActor.h @@ -9,13 +9,12 @@ #pragma once #include "Actor.h" -class CameraActor : public Actor +class CameraActor: public Actor { public: CameraActor(class Game* game); - void UpdateActor(float deltaTime) override; void ActorInput(const uint8_t* keys) override; private: - class MoveComponent* mMoveComp; -}; + class MoveComponent* pMoveComp; +}; \ No newline at end of file diff --git a/Chapter06/CircleComponent.cpp b/Chapter06/CircleComponent.cpp index 4e40d109..f57bdd8a 100644 --- a/Chapter06/CircleComponent.cpp +++ b/Chapter06/CircleComponent.cpp @@ -9,21 +9,18 @@ #include "CircleComponent.h" #include "Actor.h" -CircleComponent::CircleComponent(class Actor* owner) -:Component(owner) -,mRadius(0.0f) +CircleComponent::CircleComponent(class Actor* owner): Component(owner), mRadius(0.0f) { - } const Vector3& CircleComponent::GetCenter() const { - return mOwner->GetPosition(); + return pOwner->GetPosition(); } float CircleComponent::GetRadius() const { - return mOwner->GetScale() * mRadius; + return pOwner->GetScale() * mRadius; } bool Intersect(const CircleComponent& a, const CircleComponent& b) @@ -31,10 +28,8 @@ bool Intersect(const CircleComponent& a, const CircleComponent& b) // Calculate distance squared Vector3 diff = a.GetCenter() - b.GetCenter(); float distSq = diff.LengthSq(); - // Calculate sum of radii squared float radiiSq = a.GetRadius() + b.GetRadius(); radiiSq *= radiiSq; - return distSq <= radiiSq; -} +} \ No newline at end of file diff --git a/Chapter06/CircleComponent.h b/Chapter06/CircleComponent.h index 61c63ba9..59fbd0a9 100644 --- a/Chapter06/CircleComponent.h +++ b/Chapter06/CircleComponent.h @@ -10,17 +10,15 @@ #include "Component.h" #include "Math.h" -class CircleComponent : public Component +class CircleComponent: public Component { public: CircleComponent(class Actor* owner); - void SetRadius(float radius) { mRadius = radius; } float GetRadius() const; - const Vector3& GetCenter() const; private: float mRadius; }; -bool Intersect(const CircleComponent& a, const CircleComponent& b); +bool Intersect(const CircleComponent& a, const CircleComponent& b); \ No newline at end of file diff --git a/Chapter06/Component.cpp b/Chapter06/Component.cpp index c4ed432d..5446d684 100644 --- a/Chapter06/Component.cpp +++ b/Chapter06/Component.cpp @@ -9,19 +9,17 @@ #include "Component.h" #include "Actor.h" -Component::Component(Actor* owner, int updateOrder) - :mOwner(owner) - ,mUpdateOrder(updateOrder) +Component::Component(Actor* owner, int updateOrder): pOwner(owner), mUpdateOrder(updateOrder) { // Add to actor's vector of components - mOwner->AddComponent(this); + pOwner->AddComponent(this); } Component::~Component() { - mOwner->RemoveComponent(this); + pOwner->RemoveComponent(this); } void Component::Update(float deltaTime) { -} +} \ No newline at end of file diff --git a/Chapter06/Component.h b/Chapter06/Component.h index e2be424b..1fe03dfe 100644 --- a/Chapter06/Component.h +++ b/Chapter06/Component.h @@ -22,12 +22,11 @@ class Component // Process input for this component virtual void ProcessInput(const uint8_t* keyState) {} // Called when world transform changes - virtual void OnUpdateWorldTransform() { } - + virtual void OnUpdateWorldTransform() {} int GetUpdateOrder() const { return mUpdateOrder; } protected: // Owning actor - class Actor* mOwner; + class Actor* pOwner; // Update order of component int mUpdateOrder; -}; +}; \ No newline at end of file diff --git a/Chapter06/Game.cpp b/Chapter06/Game.cpp index cf7e03a7..688c9948 100644 --- a/Chapter06/Game.cpp +++ b/Chapter06/Game.cpp @@ -15,12 +15,8 @@ #include "CameraActor.h" #include "PlaneActor.h" -Game::Game() -:mRenderer(nullptr) -,mIsRunning(true) -,mUpdatingActors(false) +Game::Game(): pRenderer(nullptr), mIsRunning(true), mUpdatingActors(false) { - } bool Game::Initialize() @@ -30,21 +26,17 @@ bool Game::Initialize() SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } - // Create the renderer - mRenderer = new Renderer(this); - if (!mRenderer->Initialize(1024.0f, 768.0f)) + pRenderer = new Renderer(this); + if (!pRenderer->Initialize(1024.0f, 768.0f)) { SDL_Log("Failed to initialize renderer"); - delete mRenderer; - mRenderer = nullptr; + delete pRenderer; + pRenderer = nullptr; return false; } - LoadData(); - mTicksCount = SDL_GetTicks(); - return true; } @@ -70,14 +62,12 @@ void Game::ProcessInput() break; } } - const Uint8* state = SDL_GetKeyboardState(NULL); if (state[SDL_SCANCODE_ESCAPE]) { mIsRunning = false; } - - for (auto actor : mActors) + for (auto actor: mActors) { actor->ProcessInput(state); } @@ -87,44 +77,38 @@ void Game::UpdateGame() { // Compute delta time // Wait until 16ms has elapsed since last frame - while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)) - ; - + while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)); float deltaTime = (SDL_GetTicks() - mTicksCount) / 1000.0f; if (deltaTime > 0.05f) { deltaTime = 0.05f; } mTicksCount = SDL_GetTicks(); - - // Update all actors +// Update all actors: mUpdatingActors = true; - for (auto actor : mActors) + for (auto actor: mActors) { actor->Update(deltaTime); } mUpdatingActors = false; - // Move any pending actors to mActors - for (auto pending : mPendingActors) + for (auto pending: mPendingActors) { pending->ComputeWorldTransform(); mActors.emplace_back(pending); } mPendingActors.clear(); - // Add any dead actors to a temp vector std::vector deadActors; - for (auto actor : mActors) + for (auto actor: mActors) { if (actor->GetState() == Actor::EDead) { deadActors.emplace_back(actor); } } - // Delete dead actors (which removes them from mActors) - for (auto actor : deadActors) + for (auto actor: deadActors) { delete actor; } @@ -132,7 +116,7 @@ void Game::UpdateGame() void Game::GenerateOutput() { - mRenderer->Draw(); + pRenderer->Draw(); } void Game::LoadData() @@ -144,15 +128,11 @@ void Game::LoadData() Quaternion q(Vector3::UnitY, -Math::PiOver2); q = Quaternion::Concatenate(q, Quaternion(Vector3::UnitZ, Math::Pi + Math::Pi / 4.0f)); a->SetRotation(q); - MeshComponent* mc = new MeshComponent(a); - mc->SetMesh(mRenderer->GetMesh("Assets/Cube.gpmesh")); - + MeshComponent* mc = new MeshComponent(a, pRenderer->GetMesh("Assets/Cube.gpmesh")); a = new Actor(this); a->SetPosition(Vector3(200.0f, -75.0f, 0.0f)); a->SetScale(3.0f); - mc = new MeshComponent(a); - mc->SetMesh(mRenderer->GetMesh("Assets/Sphere.gpmesh")); - + mc = new MeshComponent(a, pRenderer->GetMesh("Assets/Sphere.gpmesh")); // Setup floor const float start = -1250.0f; const float size = 250.0f; @@ -164,7 +144,6 @@ void Game::LoadData() a->SetPosition(Vector3(start + i * size, start + j * size, -100.0f)); } } - // Left/right walls q = Quaternion(Vector3::UnitX, Math::PiOver2); for (int i = 0; i < 10; i++) @@ -172,12 +151,10 @@ void Game::LoadData() a = new PlaneActor(this); a->SetPosition(Vector3(start + i * size, start - size, 0.0f)); a->SetRotation(q); - a = new PlaneActor(this); a->SetPosition(Vector3(start + i * size, -start + size, 0.0f)); a->SetRotation(q); } - q = Quaternion::Concatenate(q, Quaternion(Vector3::UnitZ, Math::PiOver2)); // Forward/back walls for (int i = 0; i < 10; i++) @@ -185,33 +162,28 @@ void Game::LoadData() a = new PlaneActor(this); a->SetPosition(Vector3(start - size, start + i * size, 0.0f)); a->SetRotation(q); - a = new PlaneActor(this); a->SetPosition(Vector3(-start + size, start + i * size, 0.0f)); a->SetRotation(q); } - - // Setup lights - mRenderer->SetAmbientLight(Vector3(0.2f, 0.2f, 0.2f)); - DirectionalLight& dir = mRenderer->GetDirectionalLight(); +// Setup lights: + pRenderer->SetAmbientLight(Vector3(0.2f, 0.2f, 0.2f)); + DirectionalLight& dir = pRenderer->GetDirectionalLight(); dir.mDirection = Vector3(0.0f, -0.707f, -0.707f); dir.mDiffuseColor = Vector3(0.78f, 0.88f, 1.0f); dir.mSpecColor = Vector3(0.8f, 0.8f, 0.8f); - // Camera actor - mCameraActor = new CameraActor(this); - + pCameraActor = new CameraActor(this); // UI elements a = new Actor(this); a->SetPosition(Vector3(-350.0f, -350.0f, 0.0f)); SpriteComponent* sc = new SpriteComponent(a); - sc->SetTexture(mRenderer->GetTexture("Assets/HealthBar.png")); - + sc->SetTexture(pRenderer->GetTexture("Assets/HealthBar.png")); a = new Actor(this); a->SetPosition(Vector3(375.0f, -275.0f, 0.0f)); a->SetScale(0.75f); sc = new SpriteComponent(a); - sc->SetTexture(mRenderer->GetTexture("Assets/Radar.png")); + sc->SetTexture(pRenderer->GetTexture("Assets/Radar.png")); } void Game::UnloadData() @@ -222,19 +194,18 @@ void Game::UnloadData() { delete mActors.back(); } - - if (mRenderer) + if (pRenderer) { - mRenderer->UnloadData(); + pRenderer->UnloadData(); } } void Game::Shutdown() { UnloadData(); - if (mRenderer) + if (pRenderer) { - mRenderer->Shutdown(); + pRenderer->Shutdown(); } SDL_Quit(); } @@ -262,7 +233,6 @@ void Game::RemoveActor(Actor* actor) std::iter_swap(iter, mPendingActors.end() - 1); mPendingActors.pop_back(); } - // Is it in actors? iter = std::find(mActors.begin(), mActors.end(), actor); if (iter != mActors.end()) @@ -271,4 +241,4 @@ void Game::RemoveActor(Actor* actor) std::iter_swap(iter, mActors.end() - 1); mActors.pop_back(); } -} +} \ No newline at end of file diff --git a/Chapter06/Game.h b/Chapter06/Game.h index 6f567720..dce25038 100644 --- a/Chapter06/Game.h +++ b/Chapter06/Game.h @@ -20,30 +20,24 @@ class Game bool Initialize(); void RunLoop(); void Shutdown(); - void AddActor(class Actor* actor); void RemoveActor(class Actor* actor); - - class Renderer* GetRenderer() { return mRenderer; } + class Renderer* GetRenderer() { return pRenderer; } private: void ProcessInput(); void UpdateGame(); void GenerateOutput(); void LoadData(); void UnloadData(); - // All the actors in the game std::vector mActors; // Any pending actors std::vector mPendingActors; - - class Renderer* mRenderer; - + class Renderer* pRenderer; Uint32 mTicksCount; bool mIsRunning; // Track if we're updating actors right now bool mUpdatingActors; - // Game-specific code - class CameraActor* mCameraActor; -}; + class CameraActor* pCameraActor; +}; \ No newline at end of file diff --git a/Chapter06/Game.vcxproj b/Chapter06/Game.vcxproj index ff861c40..a907a695 100644 --- a/Chapter06/Game.vcxproj +++ b/Chapter06/Game.vcxproj @@ -57,19 +57,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode diff --git a/Chapter06/Main.cpp b/Chapter06/Main.cpp index 22ea0c69..625e0599 100644 --- a/Chapter06/Main.cpp +++ b/Chapter06/Main.cpp @@ -18,4 +18,4 @@ int main(int argc, char** argv) } game.Shutdown(); return 0; -} +} \ No newline at end of file diff --git a/Chapter06/Math.cpp b/Chapter06/Math.cpp index a16e7261..44ff7ddd 100644 --- a/Chapter06/Math.cpp +++ b/Chapter06/Math.cpp @@ -39,7 +39,6 @@ static float m4Ident[4][4] = { 0.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }; - const Matrix4 Matrix4::Identity(m4Ident); const Quaternion Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f); @@ -104,33 +103,28 @@ void Matrix4::Invert() float src[16]; float dst[16]; float det; - - // Transpose matrix +// Transpose matrix: // row 1 to col 1 src[0] = mat[0][0]; src[4] = mat[0][1]; src[8] = mat[0][2]; src[12] = mat[0][3]; - // row 2 to col 2 src[1] = mat[1][0]; src[5] = mat[1][1]; src[9] = mat[1][2]; src[13] = mat[1][3]; - // row 3 to col 3 src[2] = mat[2][0]; src[6] = mat[2][1]; src[10] = mat[2][2]; src[14] = mat[2][3]; - // row 4 to col 4 src[3] = mat[3][0]; src[7] = mat[3][1]; src[11] = mat[3][2]; src[15] = mat[3][3]; - - // Calculate cofactors +// Calculate cofactors: tmp[0] = src[10] * src[15]; tmp[1] = src[11] * src[14]; tmp[2] = src[9] * src[15]; @@ -143,7 +137,6 @@ void Matrix4::Invert() tmp[9] = src[10] * src[12]; tmp[10] = src[8] * src[13]; tmp[11] = src[9] * src[12]; - dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; @@ -160,7 +153,6 @@ void Matrix4::Invert() dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; - tmp[0] = src[2] * src[7]; tmp[1] = src[3] * src[6]; tmp[2] = src[1] * src[7]; @@ -173,7 +165,6 @@ void Matrix4::Invert() tmp[9] = src[2] * src[4]; tmp[10] = src[0] * src[5]; tmp[11] = src[1] * src[4]; - dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; @@ -190,17 +181,14 @@ void Matrix4::Invert() dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; - // Calculate determinant det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3]; - // Inverse of matrix is divided by determinant det = 1 / det; for (int j = 0; j < 16; j++) { dst[j] *= det; } - // Set it back for (int i = 0; i < 4; i++) { @@ -214,26 +202,21 @@ void Matrix4::Invert() Matrix4 Matrix4::CreateFromQuaternion(const class Quaternion& q) { float mat[4][4]; - mat[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z; mat[0][1] = 2.0f * q.x * q.y + 2.0f * q.w * q.z; mat[0][2] = 2.0f * q.x * q.z - 2.0f * q.w * q.y; mat[0][3] = 0.0f; - mat[1][0] = 2.0f * q.x * q.y - 2.0f * q.w * q.z; mat[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z; mat[1][2] = 2.0f * q.y * q.z + 2.0f * q.w * q.x; mat[1][3] = 0.0f; - mat[2][0] = 2.0f * q.x * q.z + 2.0f * q.w * q.y; mat[2][1] = 2.0f * q.y * q.z - 2.0f * q.w * q.x; mat[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y; mat[2][3] = 0.0f; - mat[3][0] = 0.0f; mat[3][1] = 0.0f; mat[3][2] = 0.0f; mat[3][3] = 1.0f; - return Matrix4(mat); -} +} \ No newline at end of file diff --git a/Chapter06/Math.h b/Chapter06/Math.h index 752963f1..53d8f0b8 100644 --- a/Chapter06/Math.h +++ b/Chapter06/Math.h @@ -24,12 +24,10 @@ namespace Math { return degrees * Pi / 180.0f; } - inline float ToDegrees(float radians) { return radians * 180.0f / Pi; } - inline bool NearZero(float val, float epsilon = 0.001f) { if (fabs(val) <= epsilon) @@ -41,70 +39,57 @@ namespace Math return false; } } - template T Max(const T& a, const T& b) { return (a < b ? b : a); } - template T Min(const T& a, const T& b) { return (a < b ? a : b); } - template T Clamp(const T& value, const T& lower, const T& upper) { return Min(upper, Max(lower, value)); } - inline float Abs(float value) { return fabs(value); } - inline float Cos(float angle) { return cosf(angle); } - inline float Sin(float angle) { return sinf(angle); } - inline float Tan(float angle) { return tanf(angle); } - inline float Acos(float value) { return acosf(value); } - inline float Atan2(float y, float x) { return atan2f(y, x); } - inline float Cot(float angle) { return 1.0f / Tan(angle); } - inline float Lerp(float a, float b, float f) { return a + f * (b - a); } - inline float Sqrt(float value) { return sqrtf(value); } - inline float Fmod(float numer, float denom) { return fmod(numer, denom); @@ -118,54 +103,41 @@ class Vector2 float x; float y; - Vector2() - :x(0.0f) - ,y(0.0f) + Vector2(): x(0.0f), y(0.0f) {} - - explicit Vector2(float inX, float inY) - :x(inX) - ,y(inY) + explicit Vector2(float inX, float inY): x(inX), y(inY) {} - // Set both components in one line void Set(float inX, float inY) { x = inX; y = inY; } - // Vector addition (a + b) friend Vector2 operator+(const Vector2& a, const Vector2& b) { return Vector2(a.x + b.x, a.y + b.y); } - // Vector subtraction (a - b) friend Vector2 operator-(const Vector2& a, const Vector2& b) { return Vector2(a.x - b.x, a.y - b.y); } - // Component-wise multiplication - // (a.x * b.x, ...) friend Vector2 operator*(const Vector2& a, const Vector2& b) { return Vector2(a.x * b.x, a.y * b.y); } - // Scalar multiplication friend Vector2 operator*(const Vector2& vec, float scalar) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar multiplication friend Vector2 operator*(float scalar, const Vector2& vec) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar *= Vector2& operator*=(float scalar) { @@ -173,7 +145,6 @@ class Vector2 y *= scalar; return *this; } - // Vector += Vector2& operator+=(const Vector2& right) { @@ -181,7 +152,6 @@ class Vector2 y += right.y; return *this; } - // Vector -= Vector2& operator-=(const Vector2& right) { @@ -189,19 +159,16 @@ class Vector2 y -= right.y; return *this; } - // Length squared of vector float LengthSq() const { return (x*x + y*y); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -209,7 +176,6 @@ class Vector2 x /= length; y /= length; } - // Normalize the provided vector static Vector2 Normalize(const Vector2& vec) { @@ -217,25 +183,21 @@ class Vector2 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector2& a, const Vector2& b) { return (a.x * b.x + a.y * b.y); } - // Lerp from A to B by f static Vector2 Lerp(const Vector2& a, const Vector2& b, float f) { return Vector2(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector2 Reflect(const Vector2& v, const Vector2& n) { return v - 2.0f * Vector2::Dot(v, n) * n; } - // Transform vector by matrix static Vector2 Transform(const Vector2& vec, const class Matrix3& mat, float w = 1.0f); @@ -254,24 +216,15 @@ class Vector3 float y; float z; - Vector3() - :x(0.0f) - ,y(0.0f) - ,z(0.0f) + Vector3(): x(0.0f), y(0.0f), z(0.0f) {} - - explicit Vector3(float inX, float inY, float inZ) - :x(inX) - ,y(inY) - ,z(inZ) + explicit Vector3(float inX, float inY, float inZ): x(inX), y(inY), z(inZ) {} - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&x); } - // Set all three components in one line void Set(float inX, float inY, float inZ) { @@ -279,37 +232,31 @@ class Vector3 y = inY; z = inZ; } - // Vector addition (a + b) friend Vector3 operator+(const Vector3& a, const Vector3& b) { return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); } - // Vector subtraction (a - b) friend Vector3 operator-(const Vector3& a, const Vector3& b) { return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); } - // Component-wise multiplication friend Vector3 operator*(const Vector3& left, const Vector3& right) { return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); } - // Scalar multiplication friend Vector3 operator*(const Vector3& vec, float scalar) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar multiplication friend Vector3 operator*(float scalar, const Vector3& vec) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar *= Vector3& operator*=(float scalar) { @@ -318,7 +265,6 @@ class Vector3 z *= scalar; return *this; } - // Vector += Vector3& operator+=(const Vector3& right) { @@ -327,7 +273,6 @@ class Vector3 z += right.z; return *this; } - // Vector -= Vector3& operator-=(const Vector3& right) { @@ -336,19 +281,16 @@ class Vector3 z -= right.z; return *this; } - // Length squared of vector float LengthSq() const { return (x*x + y*y + z*z); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -357,7 +299,6 @@ class Vector3 y /= length; z /= length; } - // Normalize the provided vector static Vector3 Normalize(const Vector3& vec) { @@ -365,13 +306,11 @@ class Vector3 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector3& a, const Vector3& b) { return (a.x * b.x + a.y * b.y + a.z * b.z); } - // Cross product between two vectors (a cross b) static Vector3 Cross(const Vector3& a, const Vector3& b) { @@ -381,23 +320,19 @@ class Vector3 temp.z = a.x * b.y - a.y * b.x; return temp; } - // Lerp from A to B by f static Vector3 Lerp(const Vector3& a, const Vector3& b, float f) { return Vector3(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector3 Reflect(const Vector3& v, const Vector3& n) { return v - 2.0f * Vector3::Dot(v, n) * n; } - static Vector3 Transform(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); // This will transform the vector and renormalize the w component static Vector3 TransformWithPerspDiv(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); - // Transform a Vector3 by a quaternion static Vector3 Transform(const Vector3& v, const class Quaternion& q); @@ -422,18 +357,15 @@ class Matrix3 { *this = Matrix3::Identity; } - explicit Matrix3(float inMat[3][3]) { memcpy(mat, inMat, 9 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication friend Matrix3 operator*(const Matrix3& left, const Matrix3& right) { @@ -443,49 +375,40 @@ class Matrix3 left.mat[0][0] * right.mat[0][0] + left.mat[0][1] * right.mat[1][0] + left.mat[0][2] * right.mat[2][0]; - retVal.mat[0][1] = left.mat[0][0] * right.mat[0][1] + left.mat[0][1] * right.mat[1][1] + left.mat[0][2] * right.mat[2][1]; - retVal.mat[0][2] = left.mat[0][0] * right.mat[0][2] + left.mat[0][1] * right.mat[1][2] + left.mat[0][2] * right.mat[2][2]; - // row 1 retVal.mat[1][0] = left.mat[1][0] * right.mat[0][0] + left.mat[1][1] * right.mat[1][0] + left.mat[1][2] * right.mat[2][0]; - retVal.mat[1][1] = left.mat[1][0] * right.mat[0][1] + left.mat[1][1] * right.mat[1][1] + left.mat[1][2] * right.mat[2][1]; - retVal.mat[1][2] = left.mat[1][0] * right.mat[0][2] + left.mat[1][1] * right.mat[1][2] + left.mat[1][2] * right.mat[2][2]; - // row 2 retVal.mat[2][0] = left.mat[2][0] * right.mat[0][0] + left.mat[2][1] * right.mat[1][0] + left.mat[2][2] * right.mat[2][0]; - retVal.mat[2][1] = left.mat[2][0] * right.mat[0][1] + left.mat[2][1] * right.mat[1][1] + left.mat[2][2] * right.mat[2][1]; - retVal.mat[2][2] = left.mat[2][0] * right.mat[0][2] + left.mat[2][1] * right.mat[1][2] + left.mat[2][2] * right.mat[2][2]; - return retVal; } @@ -556,18 +479,15 @@ class Matrix4 { *this = Matrix4::Identity; } - explicit Matrix4(float inMat[4][4]) { memcpy(mat, inMat, 16 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication (a * b) friend Matrix4 operator*(const Matrix4& a, const Matrix4& b) { @@ -578,136 +498,113 @@ class Matrix4 a.mat[0][1] * b.mat[1][0] + a.mat[0][2] * b.mat[2][0] + a.mat[0][3] * b.mat[3][0]; - retVal.mat[0][1] = a.mat[0][0] * b.mat[0][1] + a.mat[0][1] * b.mat[1][1] + a.mat[0][2] * b.mat[2][1] + a.mat[0][3] * b.mat[3][1]; - retVal.mat[0][2] = a.mat[0][0] * b.mat[0][2] + a.mat[0][1] * b.mat[1][2] + a.mat[0][2] * b.mat[2][2] + a.mat[0][3] * b.mat[3][2]; - retVal.mat[0][3] = a.mat[0][0] * b.mat[0][3] + a.mat[0][1] * b.mat[1][3] + a.mat[0][2] * b.mat[2][3] + a.mat[0][3] * b.mat[3][3]; - // row 1 retVal.mat[1][0] = a.mat[1][0] * b.mat[0][0] + a.mat[1][1] * b.mat[1][0] + a.mat[1][2] * b.mat[2][0] + a.mat[1][3] * b.mat[3][0]; - retVal.mat[1][1] = a.mat[1][0] * b.mat[0][1] + a.mat[1][1] * b.mat[1][1] + a.mat[1][2] * b.mat[2][1] + a.mat[1][3] * b.mat[3][1]; - retVal.mat[1][2] = a.mat[1][0] * b.mat[0][2] + a.mat[1][1] * b.mat[1][2] + a.mat[1][2] * b.mat[2][2] + a.mat[1][3] * b.mat[3][2]; - retVal.mat[1][3] = a.mat[1][0] * b.mat[0][3] + a.mat[1][1] * b.mat[1][3] + a.mat[1][2] * b.mat[2][3] + a.mat[1][3] * b.mat[3][3]; - // row 2 retVal.mat[2][0] = a.mat[2][0] * b.mat[0][0] + a.mat[2][1] * b.mat[1][0] + a.mat[2][2] * b.mat[2][0] + a.mat[2][3] * b.mat[3][0]; - retVal.mat[2][1] = a.mat[2][0] * b.mat[0][1] + a.mat[2][1] * b.mat[1][1] + a.mat[2][2] * b.mat[2][1] + a.mat[2][3] * b.mat[3][1]; - retVal.mat[2][2] = a.mat[2][0] * b.mat[0][2] + a.mat[2][1] * b.mat[1][2] + a.mat[2][2] * b.mat[2][2] + a.mat[2][3] * b.mat[3][2]; - retVal.mat[2][3] = a.mat[2][0] * b.mat[0][3] + a.mat[2][1] * b.mat[1][3] + a.mat[2][2] * b.mat[2][3] + a.mat[2][3] * b.mat[3][3]; - // row 3 retVal.mat[3][0] = a.mat[3][0] * b.mat[0][0] + a.mat[3][1] * b.mat[1][0] + a.mat[3][2] * b.mat[2][0] + a.mat[3][3] * b.mat[3][0]; - retVal.mat[3][1] = a.mat[3][0] * b.mat[0][1] + a.mat[3][1] * b.mat[1][1] + a.mat[3][2] * b.mat[2][1] + a.mat[3][3] * b.mat[3][1]; - retVal.mat[3][2] = a.mat[3][0] * b.mat[0][2] + a.mat[3][1] * b.mat[1][2] + a.mat[3][2] * b.mat[2][2] + a.mat[3][3] * b.mat[3][2]; - retVal.mat[3][3] = a.mat[3][0] * b.mat[0][3] + a.mat[3][1] * b.mat[1][3] + a.mat[3][2] * b.mat[2][3] + a.mat[3][3] * b.mat[3][3]; - return retVal; } - Matrix4& operator*=(const Matrix4& right) { *this = *this * right; return *this; } - // Invert the matrix - super slow void Invert(); - // Get the translation component of the matrix Vector3 GetTranslation() const { return Vector3(mat[3][0], mat[3][1], mat[3][2]); } - // Get the X axis of the matrix (forward) Vector3 GetXAxis() const { return Vector3::Normalize(Vector3(mat[0][0], mat[0][1], mat[0][2])); } - // Get the Y axis of the matrix (left) Vector3 GetYAxis() const { return Vector3::Normalize(Vector3(mat[1][0], mat[1][1], mat[1][2])); } - // Get the Z axis of the matrix (up) Vector3 GetZAxis() const { return Vector3::Normalize(Vector3(mat[2][0], mat[2][1], mat[2][2])); } - // Extract the scale component from the matrix Vector3 GetScale() const { @@ -717,7 +614,6 @@ class Matrix4 retVal.z = Vector3(mat[2][0], mat[2][1], mat[2][2]).Length(); return retVal; } - // Create a scale matrix with x, y, and z scales static Matrix4 CreateScale(float xScale, float yScale, float zScale) { @@ -730,18 +626,15 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateScale(const Vector3& scaleVector) { return CreateScale(scaleVector.x, scaleVector.y, scaleVector.z); } - // Create a scale matrix with a uniform factor static Matrix4 CreateScale(float scale) { return CreateScale(scale, scale, scale); } - // Rotation about x-axis static Matrix4 CreateRotationX(float theta) { @@ -754,7 +647,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about y-axis static Matrix4 CreateRotationY(float theta) { @@ -767,7 +659,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about z-axis static Matrix4 CreateRotationZ(float theta) { @@ -780,10 +671,8 @@ class Matrix4 }; return Matrix4(temp); } - // Create a rotation matrix from a quaternion static Matrix4 CreateFromQuaternion(const class Quaternion& q); - static Matrix4 CreateTranslation(const Vector3& trans) { float temp[4][4] = @@ -795,7 +684,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { Vector3 zaxis = Vector3::Normalize(target - eye); @@ -805,7 +693,6 @@ class Matrix4 trans.x = -Vector3::Dot(xaxis, eye); trans.y = -Vector3::Dot(yaxis, eye); trans.z = -Vector3::Dot(zaxis, eye); - float temp[4][4] = { { xaxis.x, yaxis.x, zaxis.x, 0.0f }, @@ -815,7 +702,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateOrtho(float width, float height, float near, float far) { float temp[4][4] = @@ -827,7 +713,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreatePerspectiveFOV(float fovY, float width, float height, float near, float far) { float yScale = Math::Cot(fovY / 2.0f); @@ -841,7 +726,6 @@ class Matrix4 }; return Matrix4(temp); } - // Create "Simple" View-Projection Matrix from Chapter 6 static Matrix4 CreateSimpleViewProj(float width, float height) { @@ -871,17 +755,13 @@ class Quaternion { *this = Quaternion::Identity; } - - // This directly sets the quaternion components -- - // don't use for axis/angle + // This directly sets the quaternion components -- don't use for axis/angle explicit Quaternion(float inX, float inY, float inZ, float inW) { Set(inX, inY, inZ, inW); } - // Construct the quaternion from an axis and angle - // It is assumed that axis is already normalized, - // and the angle is in radians + // It is assumed that axis is already normalized, and the angle is in radians explicit Quaternion(const Vector3& axis, float angle) { float scalar = Math::Sin(angle / 2.0f); @@ -890,7 +770,6 @@ class Quaternion z = axis.z * scalar; w = Math::Cos(angle / 2.0f); } - // Directly set the internal components void Set(float inX, float inY, float inZ, float inW) { @@ -899,24 +778,20 @@ class Quaternion z = inZ; w = inW; } - void Conjugate() { x *= -1.0f; y *= -1.0f; z *= -1.0f; } - float LengthSq() const { return (x*x + y*y + z*z + w*w); } - float Length() const { return Math::Sqrt(LengthSq()); } - void Normalize() { float length = Length(); @@ -925,7 +800,6 @@ class Quaternion z /= length; w /= length; } - // Normalize the provided quaternion static Quaternion Normalize(const Quaternion& q) { @@ -933,7 +807,6 @@ class Quaternion retVal.Normalize(); return retVal; } - // Linear interpolation static Quaternion Lerp(const Quaternion& a, const Quaternion& b, float f) { @@ -945,25 +818,20 @@ class Quaternion retVal.Normalize(); return retVal; } - static float Dot(const Quaternion& a, const Quaternion& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } - // Spherical Linear Interpolation static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float f) { float rawCosm = Quaternion::Dot(a, b); - float cosom = -rawCosm; if (rawCosm >= 0.0f) { cosom = rawCosm; } - float scale0, scale1; - if (cosom < 0.9999f) { const float omega = Math::Acos(cosom); @@ -973,17 +841,14 @@ class Quaternion } else { - // Use linear interpolation if the quaternions - // are collinear + // Use linear interpolation if the quaternions are collinear scale0 = 1.0f - f; scale1 = f; } - if (rawCosm < 0.0f) { scale1 = -scale1; } - Quaternion retVal; retVal.x = scale0 * a.x + scale1 * b.x; retVal.y = scale0 * a.y + scale1 * b.y; @@ -992,13 +857,11 @@ class Quaternion retVal.Normalize(); return retVal; } - // Concatenate // Rotate by q FOLLOWED BY p static Quaternion Concatenate(const Quaternion& q, const Quaternion& p) { Quaternion retVal; - // Vector component is: // ps * qv + qs * pv + pv x qv Vector3 qv(q.x, q.y, q.z); @@ -1007,11 +870,9 @@ class Quaternion retVal.x = newVec.x; retVal.y = newVec.y; retVal.z = newVec.z; - // Scalar component is: // ps * qs - pv . qv retVal.w = p.w * q.w - Vector3::Dot(pv, qv); - return retVal; } @@ -1030,4 +891,4 @@ namespace Color static const Vector3 LightBlue(0.68f, 0.85f, 0.9f); static const Vector3 LightPink(1.0f, 0.71f, 0.76f); static const Vector3 LightGreen(0.56f, 0.93f, 0.56f); -} +} \ No newline at end of file diff --git a/Chapter06/Mesh.cpp b/Chapter06/Mesh.cpp index 1673b2b2..fe292d4c 100644 --- a/Chapter06/Mesh.cpp +++ b/Chapter06/Mesh.cpp @@ -16,10 +16,7 @@ #include #include "Math.h" -Mesh::Mesh() - :mVertexArray(nullptr) - ,mRadius(0.0f) - ,mSpecPower(100.0f) +Mesh::Mesh(): mVertexArray(nullptr), mRadius(0.0f), mSpecPower(100.0f) { } @@ -35,35 +32,28 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) SDL_Log("File not found: Mesh %s", fileName.c_str()); return false; } - std::stringstream fileStream; fileStream << file.rdbuf(); std::string contents = fileStream.str(); rapidjson::StringStream jsonStr(contents.c_str()); rapidjson::Document doc; doc.ParseStream(jsonStr); - if (!doc.IsObject()) { SDL_Log("Mesh %s is not valid json", fileName.c_str()); return false; } - int ver = doc["version"].GetInt(); - // Check the version if (ver != 1) { SDL_Log("Mesh %s not version 1", fileName.c_str()); return false; } - mShaderName = doc["shader"].GetString(); - // Skip the vertex format/shader for now // (This is changed in a later chapter's code) size_t vertSize = 8; - // Load textures const rapidjson::Value& textures = doc["textures"]; if (!textures.IsArray() || textures.Size() < 1) @@ -71,9 +61,7 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) SDL_Log("Mesh %s has no textures, there should be at least one", fileName.c_str()); return false; } - mSpecPower = static_cast(doc["specularPower"].GetDouble()); - for (rapidjson::SizeType i = 0; i < textures.Size(); i++) { // Is this texture already loaded? @@ -91,7 +79,6 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) } mTextures.emplace_back(t); } - // Load in the vertices const rapidjson::Value& vertsJson = doc["vertices"]; if (!vertsJson.IsArray() || vertsJson.Size() < 1) @@ -99,7 +86,6 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) SDL_Log("Mesh %s has no vertices", fileName.c_str()); return false; } - std::vector vertices; vertices.reserve(vertsJson.Size() * vertSize); mRadius = 0.0f; @@ -112,20 +98,16 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) SDL_Log("Unexpected vertex format for %s", fileName.c_str()); return false; } - Vector3 pos(vert[0].GetDouble(), vert[1].GetDouble(), vert[2].GetDouble()); mRadius = Math::Max(mRadius, pos.LengthSq()); - // Add the floats for (rapidjson::SizeType i = 0; i < vert.Size(); i++) { vertices.emplace_back(static_cast(vert[i].GetDouble())); } } - // We were computing length squared earlier mRadius = Math::Sqrt(mRadius); - // Load in the indices const rapidjson::Value& indJson = doc["indices"]; if (!indJson.IsArray() || indJson.Size() < 1) @@ -133,7 +115,6 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) SDL_Log("Mesh %s has no indices", fileName.c_str()); return false; } - std::vector indices; indices.reserve(indJson.Size() * 3); for (rapidjson::SizeType i = 0; i < indJson.Size(); i++) @@ -144,15 +125,12 @@ bool Mesh::Load(const std::string & fileName, Renderer* renderer) SDL_Log("Invalid indices for %s", fileName.c_str()); return false; } - indices.emplace_back(ind[0].GetUint()); indices.emplace_back(ind[1].GetUint()); indices.emplace_back(ind[2].GetUint()); } - // Now create a vertex array - mVertexArray = new VertexArray(vertices.data(), static_cast(vertices.size()) / vertSize, - indices.data(), static_cast(indices.size())); + mVertexArray = new VertexArray(vertices.data(), static_cast(vertices.size()) / vertSize, indices.data(), static_cast(indices.size())); return true; } @@ -172,4 +150,4 @@ Texture* Mesh::GetTexture(size_t index) { return nullptr; } -} +} \ No newline at end of file diff --git a/Chapter06/MeshComponent.cpp b/Chapter06/MeshComponent.cpp index 1f4cbdb2..4df13170 100644 --- a/Chapter06/MeshComponent.cpp +++ b/Chapter06/MeshComponent.cpp @@ -8,24 +8,20 @@ #include "MeshComponent.h" #include "Shader.h" -#include "Mesh.h" #include "Actor.h" #include "Game.h" #include "Renderer.h" #include "Texture.h" #include "VertexArray.h" -MeshComponent::MeshComponent(Actor* owner) - :Component(owner) - ,mMesh(nullptr) - ,mTextureIndex(0) +MeshComponent::MeshComponent(Actor* owner, class Mesh* mesh): Component(owner), mMesh(mesh), mTextureIndex(0) { - mOwner->GetGame()->GetRenderer()->AddMeshComp(this); + pOwner->GetGame()->GetRenderer()->AddMeshComp(this); } MeshComponent::~MeshComponent() { - mOwner->GetGame()->GetRenderer()->RemoveMeshComp(this); + pOwner->GetGame()->GetRenderer()->RemoveMeshComp(this); } void MeshComponent::Draw(Shader* shader) @@ -33,8 +29,7 @@ void MeshComponent::Draw(Shader* shader) if (mMesh) { // Set the world transform - shader->SetMatrixUniform("uWorldTransform", - mOwner->GetWorldTransform()); + shader->SetMatrixUniform("uWorldTransform", pOwner->GetWorldTransform()); // Set specular power shader->SetFloatUniform("uSpecPower", mMesh->GetSpecPower()); // Set the active texture @@ -49,4 +44,4 @@ void MeshComponent::Draw(Shader* shader) // Draw glDrawElements(GL_TRIANGLES, va->GetNumIndices(), GL_UNSIGNED_INT, nullptr); } -} +} \ No newline at end of file diff --git a/Chapter06/MeshComponent.h b/Chapter06/MeshComponent.h index 48765568..52d49ba8 100644 --- a/Chapter06/MeshComponent.h +++ b/Chapter06/MeshComponent.h @@ -9,18 +9,21 @@ #pragma once #include "Component.h" #include +#include "Mesh.h" -class MeshComponent : public Component +class MeshComponent: public Component { public: - MeshComponent(class Actor* owner); + MeshComponent(class Actor* owner, class Mesh* mesh); ~MeshComponent(); // Draw this mesh component virtual void Draw(class Shader* shader); // Set the mesh/texture index used by mesh component virtual void SetMesh(class Mesh* mesh) { mMesh = mesh; } + // Get name of shader + inline const std::string& GetShaderName() const { return mMesh->GetShaderName(); } void SetTextureIndex(size_t index) { mTextureIndex = index; } protected: class Mesh* mMesh; size_t mTextureIndex; -}; +}; \ No newline at end of file diff --git a/Chapter06/MoveComponent.cpp b/Chapter06/MoveComponent.cpp index 5b51c6fc..8b96a42c 100644 --- a/Chapter06/MoveComponent.cpp +++ b/Chapter06/MoveComponent.cpp @@ -9,32 +9,27 @@ #include "MoveComponent.h" #include "Actor.h" -MoveComponent::MoveComponent(class Actor* owner, int updateOrder) -:Component(owner, updateOrder) -,mAngularSpeed(0.0f) -,mForwardSpeed(0.0f) +MoveComponent::MoveComponent(class Actor* owner, int updateOrder): Component(owner, updateOrder), mAngularSpeed(0.0f), mForwardSpeed(0.0f) { - } void MoveComponent::Update(float deltaTime) { if (!Math::NearZero(mAngularSpeed)) { - Quaternion rot = mOwner->GetRotation(); + Quaternion rot = pOwner->GetRotation(); float angle = mAngularSpeed * deltaTime; // Create quaternion for incremental rotation // (Rotate about up axis) Quaternion inc(Vector3::UnitZ, angle); // Concatenate old and new quaternion rot = Quaternion::Concatenate(rot, inc); - mOwner->SetRotation(rot); + pOwner->SetRotation(rot); } - if (!Math::NearZero(mForwardSpeed)) { - Vector3 pos = mOwner->GetPosition(); - pos += mOwner->GetForward() * mForwardSpeed * deltaTime; - mOwner->SetPosition(pos); + Vector3 pos = pOwner->GetPosition(); + pos += pOwner->GetForward() * mForwardSpeed * deltaTime; + pOwner->SetPosition(pos); } -} +} \ No newline at end of file diff --git a/Chapter06/MoveComponent.h b/Chapter06/MoveComponent.h index def7d389..c737e66b 100644 --- a/Chapter06/MoveComponent.h +++ b/Chapter06/MoveComponent.h @@ -9,13 +9,12 @@ #pragma once #include "Component.h" -class MoveComponent : public Component +class MoveComponent: public Component { public: // Lower update order to update first MoveComponent(class Actor* owner, int updateOrder = 10); void Update(float deltaTime) override; - float GetAngularSpeed() const { return mAngularSpeed; } float GetForwardSpeed() const { return mForwardSpeed; } void SetAngularSpeed(float speed) { mAngularSpeed = speed; } @@ -23,4 +22,4 @@ class MoveComponent : public Component private: float mAngularSpeed; float mForwardSpeed; -}; +}; \ No newline at end of file diff --git a/Chapter06/PlaneActor.cpp b/Chapter06/PlaneActor.cpp index 5398ca4c..bfaa3c4b 100644 --- a/Chapter06/PlaneActor.cpp +++ b/Chapter06/PlaneActor.cpp @@ -11,10 +11,8 @@ #include "Renderer.h" #include "MeshComponent.h" -PlaneActor::PlaneActor(Game* game) - :Actor(game) +PlaneActor::PlaneActor(Game* game): Actor(game) { SetScale(10.0f); - MeshComponent* mc = new MeshComponent(this); - mc->SetMesh(GetGame()->GetRenderer()->GetMesh("Assets/Plane.gpmesh")); -} + MeshComponent* mc = new MeshComponent(this, game->GetRenderer()->GetMesh("Assets/Plane.gpmesh")); +} \ No newline at end of file diff --git a/Chapter06/PlaneActor.h b/Chapter06/PlaneActor.h index 8187b64a..ca323e87 100644 --- a/Chapter06/PlaneActor.h +++ b/Chapter06/PlaneActor.h @@ -9,7 +9,7 @@ #pragma once #include "Actor.h" -class PlaneActor : public Actor +class PlaneActor: public Actor { public: PlaneActor(class Game* game); diff --git a/Chapter06/Renderer.cpp b/Chapter06/Renderer.cpp index 43a25fe8..00e7bd13 100644 --- a/Chapter06/Renderer.cpp +++ b/Chapter06/Renderer.cpp @@ -16,10 +16,7 @@ #include "MeshComponent.h" #include -Renderer::Renderer(Game* game) - :mGame(game) - ,mSpriteShader(nullptr) - ,mMeshShader(nullptr) +Renderer::Renderer(Game* game): pGame(game), pCurrentShader(nullptr) { } @@ -31,7 +28,6 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) { mScreenWidth = screenWidth; mScreenHeight = screenHeight; - // Set OpenGL attributes // Use the core OpenGL profile SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); @@ -48,18 +44,14 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Force OpenGL to use hardware acceleration SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); - - mWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 6)", 100, 100, - static_cast(mScreenWidth), static_cast(mScreenHeight), SDL_WINDOW_OPENGL); - if (!mWindow) + pWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 6)", 100, 100, static_cast(mScreenWidth), static_cast(mScreenHeight), SDL_WINDOW_OPENGL); + if (!pWindow) { SDL_Log("Failed to create window: %s", SDL_GetError()); return false; } - // Create an OpenGL context - mContext = SDL_GL_CreateContext(mWindow); - + mContext = SDL_GL_CreateContext(pWindow); // Initialize GLEW glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) @@ -67,33 +59,26 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) SDL_Log("Failed to initialize GLEW."); return false; } - - // On some platforms, GLEW will emit a benign error code, - // so clear it + // On some platforms, GLEW will emit a benign error code, so clear it glGetError(); - // Make sure we can create/compile shaders if (!LoadShaders()) { SDL_Log("Failed to load shaders."); return false; } - // Create quad for drawing sprites CreateSpriteVerts(); - return true; } void Renderer::Shutdown() { - delete mSpriteVerts; - mSpriteShader->Unload(); - delete mSpriteShader; - mMeshShader->Unload(); - delete mMeshShader; + delete pSpriteVerts; + // NOTE: Shaders are unloaded elsewhere + delete pCurrentShader; SDL_GL_DeleteContext(mContext); - SDL_DestroyWindow(mWindow); + SDL_DestroyWindow(pWindow); } void Renderer::UnloadData() @@ -105,7 +90,6 @@ void Renderer::UnloadData() delete i.second; } mTextures.clear(); - // Destroy meshes for (auto i : mMeshes) { @@ -113,30 +97,41 @@ void Renderer::UnloadData() delete i.second; } mMeshes.clear(); + // Destroy shaders + for (auto i : mShaders) + { + i.second->Unload(); + delete i.second; + } + mShaders.clear(); } void Renderer::Draw() { - // Set the clear color to light grey + // Set the clear color to black glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the color buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Draw mesh components // Enable depth buffering/disable alpha blend glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); // Set the mesh shader active - mMeshShader->SetActive(); + SetCurrentShader("Mesh"); // Update view-projection matrix - mMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); + pCurrentShader->SetMatrixUniform("uViewProj", mView * mProjection); // Update lighting uniforms - SetLightUniforms(mMeshShader); - for (auto mc : mMeshComps) + SetLightUniforms(pCurrentShader); + // Loop through each mesh-shader + for (auto mclist: mMeshComps) { - mc->Draw(mMeshShader); + SetCurrentShader(mclist.first); + // Loop through each mesh component using the current shader + for (MeshComponent* mc: mclist.second) + { + mc->Draw(pCurrentShader); + } } - // Draw all sprite components // Disable depth buffering glDisable(GL_DEPTH_TEST); @@ -144,17 +139,15 @@ void Renderer::Draw() glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); - - // Set shader/vao as active - mSpriteShader->SetActive(); - mSpriteVerts->SetActive(); - for (auto sprite : mSprites) + // Set shader/VAO as active + SetCurrentShader("Sprite"); + pSpriteVerts->SetActive(); + for (auto sprite: mSprites) { - sprite->Draw(mSpriteShader); + sprite->Draw(pCurrentShader); } - // Swap the buffers - SDL_GL_SwapWindow(mWindow); + SDL_GL_SwapWindow(pWindow); } void Renderer::AddSprite(SpriteComponent* sprite) @@ -163,16 +156,13 @@ void Renderer::AddSprite(SpriteComponent* sprite) // (The first element with a higher draw order than me) int myDrawOrder = sprite->GetDrawOrder(); auto iter = mSprites.begin(); - for (; - iter != mSprites.end(); - ++iter) + for (; iter != mSprites.end(); ++iter) { if (myDrawOrder < (*iter)->GetDrawOrder()) { break; } } - // Inserts element before position of iterator mSprites.insert(iter, sprite); } @@ -185,13 +175,30 @@ void Renderer::RemoveSprite(SpriteComponent* sprite) void Renderer::AddMeshComp(MeshComponent* mesh) { - mMeshComps.emplace_back(mesh); + // Is the shader in the map? + auto iter = mMeshComps.find(mesh->GetShaderName()); + if (iter != mMeshComps.end()) // Yes + { + // Add the mesh component to the list (vector) + iter->second.emplace_back(mesh); + } + else // No + { + // Create a new vector containing the mesh component + std::vector mcvec = {mesh}; + // Add the pair to the map + mMeshComps.emplace(mesh->GetShaderName(), mcvec); + } } void Renderer::RemoveMeshComp(MeshComponent* mesh) { - auto iter = std::find(mMeshComps.begin(), mMeshComps.end(), mesh); - mMeshComps.erase(iter); + // Retrive the mesh component vector for the specific shader + std::vector mcvec = mMeshComps.at(mesh->GetShaderName()); + // Loop through the vector until you find what you are looking for + auto iter = std::find(mcvec.begin(), mcvec.end(), mesh); + // remove the mesh componment from the list (vector) + mcvec.erase(iter); } Texture* Renderer::GetTexture(const std::string& fileName) @@ -242,33 +249,55 @@ Mesh* Renderer::GetMesh(const std::string & fileName) return m; } +bool Renderer::SetCurrentShader(const std::string& fileName) +{ + auto iter = mShaders.find(fileName); + if (iter != mShaders.end()) + { + Shader* sh = iter->second; + pCurrentShader = sh; + sh->SetActive(); + return true; + } + return false; +} + +bool Renderer::LoadShader(const std::string& name, const std::string& vertFile, const std::string& fragFile) +{ + // Create a new shader + Shader* sh = new Shader(); + if (sh->Load(vertFile, fragFile)) + { + mShaders.emplace(name, sh); + pCurrentShader = sh; + sh->SetActive(); + return true; + } + // Loading failed, so delete the Shader + delete sh; + sh = nullptr; + return false; +} + bool Renderer::LoadShaders() { // Create sprite shader - mSpriteShader = new Shader(); - if (!mSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag")) + if(!LoadShader("Sprite", "Shaders/Sprite.vert", "Shaders/Sprite.frag")) { return false; } - - mSpriteShader->SetActive(); // Set the view-projection matrix Matrix4 viewProj = Matrix4::CreateSimpleViewProj(mScreenWidth, mScreenHeight); - mSpriteShader->SetMatrixUniform("uViewProj", viewProj); - + pCurrentShader->SetMatrixUniform("uViewProj", viewProj); // Create basic mesh shader - mMeshShader = new Shader(); - if (!mMeshShader->Load("Shaders/Phong.vert", "Shaders/Phong.frag")) + if (!LoadShader("Mesh", "Shaders/Phong.vert", "Shaders/Phong.frag")) { return false; } - - mMeshShader->SetActive(); // Set the view-projection matrix mView = Matrix4::CreateLookAt(Vector3::Zero, Vector3::UnitX, Vector3::UnitZ); - mProjection = Matrix4::CreatePerspectiveFOV(Math::ToRadians(70.0f), - mScreenWidth, mScreenHeight, 25.0f, 10000.0f); - mMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); + mProjection = Matrix4::CreatePerspectiveFOV(Math::ToRadians(70.0f), mScreenWidth, mScreenHeight, 25.0f, 10000.0f); + pCurrentShader->SetMatrixUniform("uViewProj", mView * mProjection); return true; } @@ -280,13 +309,11 @@ void Renderer::CreateSpriteVerts() 0.5f,-0.5f, 0.f, 0.f, 0.f, 0.0f, 1.f, 1.f, // bottom right -0.5f,-0.5f, 0.f, 0.f, 0.f, 0.0f, 0.f, 1.f // bottom left }; - unsigned int indices[] = { 0, 1, 2, 2, 3, 0 }; - - mSpriteVerts = new VertexArray(vertices, 4, indices, 6); + pSpriteVerts = new VertexArray(vertices, 4, indices, 6); } void Renderer::SetLightUniforms(Shader* shader) @@ -298,10 +325,7 @@ void Renderer::SetLightUniforms(Shader* shader) // Ambient light shader->SetVectorUniform("uAmbientLight", mAmbientLight); // Directional light - shader->SetVectorUniform("uDirLight.mDirection", - mDirLight.mDirection); - shader->SetVectorUniform("uDirLight.mDiffuseColor", - mDirLight.mDiffuseColor); - shader->SetVectorUniform("uDirLight.mSpecColor", - mDirLight.mSpecColor); -} + shader->SetVectorUniform("uDirLight.mDirection", mDirLight.mDirection); + shader->SetVectorUniform("uDirLight.mDiffuseColor", mDirLight.mDiffuseColor); + shader->SetVectorUniform("uDirLight.mSpecColor", mDirLight.mSpecColor); +} \ No newline at end of file diff --git a/Chapter06/Renderer.h b/Chapter06/Renderer.h index 12746df2..4fa8ee85 100644 --- a/Chapter06/Renderer.h +++ b/Chapter06/Renderer.h @@ -28,69 +28,56 @@ class Renderer public: Renderer(class Game* game); ~Renderer(); - bool Initialize(float screenWidth, float screenHeight); void Shutdown(); void UnloadData(); - void Draw(); - void AddSprite(class SpriteComponent* sprite); void RemoveSprite(class SpriteComponent* sprite); - void AddMeshComp(class MeshComponent* mesh); void RemoveMeshComp(class MeshComponent* mesh); - class Texture* GetTexture(const std::string& fileName); class Mesh* GetMesh(const std::string& fileName); - + bool SetCurrentShader(const std::string& fileName); void SetViewMatrix(const Matrix4& view) { mView = view; } - void SetAmbientLight(const Vector3& ambient) { mAmbientLight = ambient; } DirectionalLight& GetDirectionalLight() { return mDirLight; } - float GetScreenWidth() const { return mScreenWidth; } float GetScreenHeight() const { return mScreenHeight; } private: + // Creates a new shader and sets it as the current shader + bool LoadShader(const std::string& name, const std::string& vertFile, const std::string& fragFile); + // Loads all shaders bool LoadShaders(); void CreateSpriteVerts(); void SetLightUniforms(class Shader* shader); - // Map of textures loaded std::unordered_map mTextures; // Map of meshes loaded std::unordered_map mMeshes; - + // Map of shaders loaded + std::unordered_map mShaders; + // Map linking mesh components to specific shaders + std::unordered_map> mMeshComps; // All the sprite components drawn std::vector mSprites; - - // All mesh components drawn - std::vector mMeshComps; - // Game - class Game* mGame; - - // Sprite shader - class Shader* mSpriteShader; + class Game* pGame; + // Current shader + class Shader* pCurrentShader; // Sprite vertex array - class VertexArray* mSpriteVerts; - - // Mesh shader - class Shader* mMeshShader; - + class VertexArray* pSpriteVerts; // View/projection for 3D shaders Matrix4 mView; Matrix4 mProjection; // Width/height of screen float mScreenWidth; float mScreenHeight; - // Lighting data Vector3 mAmbientLight; DirectionalLight mDirLight; - // Window - SDL_Window* mWindow; + SDL_Window* pWindow; // OpenGL context SDL_GLContext mContext; }; \ No newline at end of file diff --git a/Chapter06/Shader.cpp b/Chapter06/Shader.cpp index cae3ac07..a9702108 100644 --- a/Chapter06/Shader.cpp +++ b/Chapter06/Shader.cpp @@ -12,45 +12,32 @@ #include #include -Shader::Shader() - : mShaderProgram(0) - , mVertexShader(0) - , mFragShader(0) +Shader::Shader(): mShaderProgram(0), mVertexShader(0), mFragShader(0) { - } Shader::~Shader() { - } bool Shader::Load(const std::string& vertName, const std::string& fragName) { // Compile vertex and pixel shaders - if (!CompileShader(vertName, - GL_VERTEX_SHADER, - mVertexShader) || - !CompileShader(fragName, - GL_FRAGMENT_SHADER, - mFragShader)) + if (!CompileShader(vertName, GL_VERTEX_SHADER, mVertexShader) || !CompileShader(fragName, GL_FRAGMENT_SHADER, mFragShader)) { return false; } - // Now create a shader program that // links together the vertex/frag shaders mShaderProgram = glCreateProgram(); glAttachShader(mShaderProgram, mVertexShader); glAttachShader(mShaderProgram, mFragShader); glLinkProgram(mShaderProgram); - // Verify that the program linked successfully if (!IsValidProgram()) { return false; } - return true; } @@ -90,9 +77,7 @@ void Shader::SetFloatUniform(const char* name, float value) glUniform1f(loc, value); } -bool Shader::CompileShader(const std::string& fileName, - GLenum shaderType, - GLuint& outShader) +bool Shader::CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader) { // Open file std::ifstream shaderFile(fileName); @@ -103,13 +88,11 @@ bool Shader::CompileShader(const std::string& fileName, sstream << shaderFile.rdbuf(); std::string contents = sstream.str(); const char* contentsChar = contents.c_str(); - // Create a shader of the specified type outShader = glCreateShader(shaderType); // Set the source characters and try to compile glShaderSource(outShader, 1, &(contentsChar), nullptr); glCompileShader(outShader); - if (!IsCompiled(outShader)) { SDL_Log("Failed to compile shader %s", fileName.c_str()); @@ -121,7 +104,6 @@ bool Shader::CompileShader(const std::string& fileName, SDL_Log("Shader file not found: %s", fileName.c_str()); return false; } - return true; } @@ -130,7 +112,6 @@ bool Shader::IsCompiled(GLuint shader) GLint status; // Query the compile status glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { char buffer[512]; @@ -139,13 +120,11 @@ bool Shader::IsCompiled(GLuint shader) SDL_Log("GLSL Compile Failed:\n%s", buffer); return false; } - return true; } bool Shader::IsValidProgram() { - GLint status; // Query the link status glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &status); @@ -157,6 +136,5 @@ bool Shader::IsValidProgram() SDL_Log("GLSL Link Status:\n%s", buffer); return false; } - return true; -} +} \ No newline at end of file diff --git a/Chapter06/Shader.h b/Chapter06/Shader.h index 929c9e41..f9c5e33e 100644 --- a/Chapter06/Shader.h +++ b/Chapter06/Shader.h @@ -29,10 +29,7 @@ class Shader void SetFloatUniform(const char* name, float value); private: // Tries to compile the specified shader - bool CompileShader(const std::string& fileName, - GLenum shaderType, - GLuint& outShader); - + bool CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader); // Tests whether shader compiled successfully bool IsCompiled(GLuint shader); // Tests whether vertex/fragment programs link @@ -42,4 +39,4 @@ class Shader GLuint mVertexShader; GLuint mFragShader; GLuint mShaderProgram; -}; +}; \ No newline at end of file diff --git a/Chapter06/Shaders/BasicMesh.frag b/Chapter06/Shaders/BasicMesh.frag index 481a669a..54f0924f 100644 --- a/Chapter06/Shaders/BasicMesh.frag +++ b/Chapter06/Shaders/BasicMesh.frag @@ -11,10 +11,8 @@ // Tex coord input from vertex shader in vec2 fragTexCoord; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; @@ -22,4 +20,4 @@ void main() { // Sample color from texture outColor = texture(uTexture, fragTexCoord); -} +} \ No newline at end of file diff --git a/Chapter06/Shaders/BasicMesh.vert b/Chapter06/Shaders/BasicMesh.vert index 7d21ad0d..297d197b 100644 --- a/Chapter06/Shaders/BasicMesh.vert +++ b/Chapter06/Shaders/BasicMesh.vert @@ -12,12 +12,10 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is normal, 2 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoord; - // Any vertex outputs (other than position) out vec2 fragTexCoord; @@ -27,7 +25,6 @@ void main() vec4 pos = vec4(inPosition, 1.0); // Transform to position world space, then clip space gl_Position = pos * uWorldTransform * uViewProj; - // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter06/Shaders/Phong.frag b/Chapter06/Shaders/Phong.frag index 7bb2678c..081fa77e 100644 --- a/Chapter06/Shaders/Phong.frag +++ b/Chapter06/Shaders/Phong.frag @@ -16,13 +16,10 @@ in vec2 fragTexCoord; in vec3 fragNormal; // Position (in world space) in vec3 fragWorldPos; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; - // Create a struct for directional light struct DirectionalLight { @@ -33,7 +30,6 @@ struct DirectionalLight // Specular color vec3 mSpecColor; }; - // Uniforms for lighting // Camera position (in world space) uniform vec3 uCameraPos; @@ -41,7 +37,6 @@ uniform vec3 uCameraPos; uniform float uSpecPower; // Ambient light level uniform vec3 uAmbientLight; - // Directional Light uniform DirectionalLight uDirLight; @@ -55,7 +50,6 @@ void main() vec3 V = normalize(uCameraPos - fragWorldPos); // Reflection of -L about N vec3 R = normalize(reflect(-L, N)); - // Compute phong reflection vec3 Phong = uAmbientLight; float NdotL = dot(N, L); @@ -65,7 +59,6 @@ void main() vec3 Specular = uDirLight.mSpecColor * pow(max(0.0, dot(R, V)), uSpecPower); Phong += Diffuse + Specular; } - // Final color is texture color times phong light (alpha = 1) outColor = texture(uTexture, fragTexCoord) * vec4(Phong, 1.0f); -} +} \ No newline at end of file diff --git a/Chapter06/Shaders/Phong.vert b/Chapter06/Shaders/Phong.vert index af5078dc..cfa49a2b 100644 --- a/Chapter06/Shaders/Phong.vert +++ b/Chapter06/Shaders/Phong.vert @@ -12,12 +12,10 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is normal, 2 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoord; - // Any vertex outputs (other than position) out vec2 fragTexCoord; // Normal (in world space) @@ -35,10 +33,8 @@ void main() fragWorldPos = pos.xyz; // Transform to clip space gl_Position = pos * uViewProj; - // Transform normal into world space (w = 0) fragNormal = (vec4(inNormal, 0.0f) * uWorldTransform).xyz; - // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter06/Shaders/Sprite.frag b/Chapter06/Shaders/Sprite.frag index 481a669a..54f0924f 100644 --- a/Chapter06/Shaders/Sprite.frag +++ b/Chapter06/Shaders/Sprite.frag @@ -11,10 +11,8 @@ // Tex coord input from vertex shader in vec2 fragTexCoord; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; @@ -22,4 +20,4 @@ void main() { // Sample color from texture outColor = texture(uTexture, fragTexCoord); -} +} \ No newline at end of file diff --git a/Chapter06/Shaders/Sprite.vert b/Chapter06/Shaders/Sprite.vert index 7d21ad0d..297d197b 100644 --- a/Chapter06/Shaders/Sprite.vert +++ b/Chapter06/Shaders/Sprite.vert @@ -12,12 +12,10 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is normal, 2 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoord; - // Any vertex outputs (other than position) out vec2 fragTexCoord; @@ -27,7 +25,6 @@ void main() vec4 pos = vec4(inPosition, 1.0); // Transform to position world space, then clip space gl_Position = pos * uWorldTransform * uViewProj; - // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter06/SpriteComponent.cpp b/Chapter06/SpriteComponent.cpp index eb7b77aa..f81296db 100644 --- a/Chapter06/SpriteComponent.cpp +++ b/Chapter06/SpriteComponent.cpp @@ -13,40 +13,29 @@ #include "Game.h" #include "Renderer.h" -SpriteComponent::SpriteComponent(Actor* owner, int drawOrder) - :Component(owner) - ,mTexture(nullptr) - ,mDrawOrder(drawOrder) - ,mTexWidth(0) - ,mTexHeight(0) +SpriteComponent::SpriteComponent(Actor* owner, int drawOrder): Component(owner), pTexture(nullptr), mDrawOrder(drawOrder), mTexWidth(0), mTexHeight(0) { - mOwner->GetGame()->GetRenderer()->AddSprite(this); + pOwner->GetGame()->GetRenderer()->AddSprite(this); } SpriteComponent::~SpriteComponent() { - mOwner->GetGame()->GetRenderer()->RemoveSprite(this); + pOwner->GetGame()->GetRenderer()->RemoveSprite(this); } void SpriteComponent::Draw(Shader* shader) { - if (mTexture) + if (pTexture) { // Scale the quad by the width/height of texture - Matrix4 scaleMat = Matrix4::CreateScale( - static_cast(mTexWidth), - static_cast(mTexHeight), - 1.0f); - - Matrix4 world = scaleMat * mOwner->GetWorldTransform(); - + Matrix4 scaleMat = Matrix4::CreateScale(static_cast(mTexWidth), static_cast(mTexHeight), 1.0f); + Matrix4 world = scaleMat * pOwner->GetWorldTransform(); // Since all sprites use the same shader/vertices, // the game first sets them active before any sprite draws - // Set world transform shader->SetMatrixUniform("uWorldTransform", world); // Set current texture - mTexture->SetActive(); + pTexture->SetActive(); // Draw quad glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); } @@ -54,8 +43,8 @@ void SpriteComponent::Draw(Shader* shader) void SpriteComponent::SetTexture(Texture* texture) { - mTexture = texture; + pTexture = texture; // Set width/height mTexWidth = texture->GetWidth(); mTexHeight = texture->GetHeight(); -} +} \ No newline at end of file diff --git a/Chapter06/SpriteComponent.h b/Chapter06/SpriteComponent.h index 6c5642f2..581cb883 100644 --- a/Chapter06/SpriteComponent.h +++ b/Chapter06/SpriteComponent.h @@ -9,22 +9,20 @@ #pragma once #include "Component.h" #include "SDL/SDL.h" -class SpriteComponent : public Component +class SpriteComponent: public Component { public: // (Lower draw order corresponds with further back) SpriteComponent(class Actor* owner, int drawOrder = 100); ~SpriteComponent(); - virtual void Draw(class Shader* shader); virtual void SetTexture(class Texture* texture); - int GetDrawOrder() const { return mDrawOrder; } int GetTexHeight() const { return mTexHeight; } int GetTexWidth() const { return mTexWidth; } protected: - class Texture* mTexture; + class Texture* pTexture; int mDrawOrder; int mTexWidth; int mTexHeight; -}; +}; \ No newline at end of file diff --git a/Chapter06/Texture.cpp b/Chapter06/Texture.cpp index ddde35f0..a2c632c9 100644 --- a/Chapter06/Texture.cpp +++ b/Chapter06/Texture.cpp @@ -11,50 +11,35 @@ #include #include -Texture::Texture() -:mTextureID(0) -,mWidth(0) -,mHeight(0) +Texture::Texture(): mTextureID(0), mWidth(0), mHeight(0) { - } Texture::~Texture() { - } bool Texture::Load(const std::string& fileName) { int channels = 0; - - unsigned char* image = SOIL_load_image(fileName.c_str(), - &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); - + unsigned char* image = SOIL_load_image(fileName.c_str(), &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); if (image == nullptr) { SDL_Log("SOIL failed to load image %s: %s", fileName.c_str(), SOIL_last_result()); return false; } - int format = GL_RGB; if (channels == 4) { format = GL_RGBA; } - glGenTextures(1, &mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID); - - glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, - GL_UNSIGNED_BYTE, image); - + glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, GL_UNSIGNED_BYTE, image); SOIL_free_image_data(image); - // Enable linear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - return true; } @@ -66,4 +51,4 @@ void Texture::Unload() void Texture::SetActive() { glBindTexture(GL_TEXTURE_2D, mTextureID); -} +} \ No newline at end of file diff --git a/Chapter06/Texture.h b/Chapter06/Texture.h index 6c8892fd..b2059450 100644 --- a/Chapter06/Texture.h +++ b/Chapter06/Texture.h @@ -13,16 +13,13 @@ class Texture public: Texture(); ~Texture(); - bool Load(const std::string& fileName); void Unload(); - void SetActive(); - int GetWidth() const { return mWidth; } int GetHeight() const { return mHeight; } private: unsigned int mTextureID; int mWidth; int mHeight; -}; +}; \ No newline at end of file diff --git a/Chapter06/VertexArray.cpp b/Chapter06/VertexArray.cpp index faddcf6c..e97c3bdd 100644 --- a/Chapter06/VertexArray.cpp +++ b/Chapter06/VertexArray.cpp @@ -9,25 +9,19 @@ #include "VertexArray.h" #include -VertexArray::VertexArray(const float* verts, unsigned int numVerts, - const unsigned int* indices, unsigned int numIndices) - :mNumVerts(numVerts) - ,mNumIndices(numIndices) +VertexArray::VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices): mNumVerts(numVerts), mNumIndices(numIndices) { // Create vertex array glGenVertexArrays(1, &mVertexArray); glBindVertexArray(mVertexArray); - // Create vertex buffer glGenBuffers(1, &mVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); glBufferData(GL_ARRAY_BUFFER, numVerts * 8 * sizeof(float), verts, GL_STATIC_DRAW); - // Create index buffer glGenBuffers(1, &mIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned int), indices, GL_STATIC_DRAW); - // Specify the vertex attributes // (For now, assume one vertex format) // Position is 3 floats @@ -35,12 +29,10 @@ VertexArray::VertexArray(const float* verts, unsigned int numVerts, glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0); // Normal is 3 floats glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), - reinterpret_cast(sizeof(float) * 3)); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast(sizeof(float) * 3)); // Texture coordinates is 2 floats glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), - reinterpret_cast(sizeof(float) * 6)); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast(sizeof(float) * 6)); } VertexArray::~VertexArray() @@ -53,4 +45,4 @@ VertexArray::~VertexArray() void VertexArray::SetActive() { glBindVertexArray(mVertexArray); -} +} \ No newline at end of file diff --git a/Chapter06/VertexArray.h b/Chapter06/VertexArray.h index 5deddc4d..480a254b 100644 --- a/Chapter06/VertexArray.h +++ b/Chapter06/VertexArray.h @@ -10,10 +10,8 @@ class VertexArray { public: - VertexArray(const float* verts, unsigned int numVerts, - const unsigned int* indices, unsigned int numIndices); + VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices); ~VertexArray(); - void SetActive(); unsigned int GetNumIndices() const { return mNumIndices; } unsigned int GetNumVerts() const { return mNumVerts; } From bd94a4ced93c685009e5d2e1c9c6b4a553e5403a Mon Sep 17 00:00:00 2001 From: bobnone Date: Fri, 20 May 2022 07:43:03 -0500 Subject: [PATCH 5/6] Finished 6.2 --- Chapter06/Game.cpp | 33 +++++++++++++++++++ Chapter06/Renderer.cpp | 15 +++++++-- Chapter06/Renderer.h | 15 +++++++++ Chapter06/Shader.cpp | 7 ++++ Chapter06/Shader.h | 2 ++ Chapter06/Shaders/Phong.frag | 62 ++++++++++++++++++++++++++++++------ 6 files changed, 122 insertions(+), 12 deletions(-) diff --git a/Chapter06/Game.cpp b/Chapter06/Game.cpp index 688c9948..d2f50fc9 100644 --- a/Chapter06/Game.cpp +++ b/Chapter06/Game.cpp @@ -167,11 +167,44 @@ void Game::LoadData() a->SetRotation(q); } // Setup lights: + // Directional Light pRenderer->SetAmbientLight(Vector3(0.2f, 0.2f, 0.2f)); DirectionalLight& dir = pRenderer->GetDirectionalLight(); dir.mDirection = Vector3(0.0f, -0.707f, -0.707f); dir.mDiffuseColor = Vector3(0.78f, 0.88f, 1.0f); dir.mSpecColor = Vector3(0.8f, 0.8f, 0.8f); + // Point Lights + std::vector* plvec = pRenderer->GetPointLights(); + // Point Light1 + PointLight pl1; + pl1.mWorldPos = Vector3(0.0f, 0.0f, 0.0f); + pl1.mDiffuseColor = Vector3(0.0f, 1.0f, 0.0f); + pl1.mSpecColor = Vector3(0.0f, 1.0f, 0.0f); + pl1.mInnerRadius = 0.0f; + pl1.mOuterRadius = 500.0f; + plvec->emplace_back(pl1); + // Point Light2 + PointLight pl2; + pl2.mWorldPos = Vector3(500.0f, 500.0f, 200.0f); + pl2.mDiffuseColor = Vector3(0.0f, 0.0f, 1.0f); + pl2.mSpecColor = Vector3(0.0f, 0.0f, 1.0f); + pl2.mInnerRadius = 0.0f; + pl2.mOuterRadius = 500.0f; + plvec->emplace_back(pl2); + PointLight pl3; + pl3.mWorldPos = Vector3(0.0f, -200.0f, 0.0f); + pl3.mDiffuseColor = Vector3(1.0f, 0.0f, 0.0f); + pl3.mSpecColor = Vector3(1.0f, 0.0f, 0.0f); + pl3.mInnerRadius = 0.0f; + pl3.mOuterRadius = 500.0f; + plvec->emplace_back(pl3); + PointLight pl4; + pl4.mWorldPos = Vector3(-1000.0f, 1000.0f, 0.0f); + pl4.mDiffuseColor = Vector3(1.0f, 1.0f, 0.0f); + pl4.mSpecColor = Vector3(1.0f, 1.0f, 0.0f); + pl4.mInnerRadius = 0.0f; + pl4.mOuterRadius = 500.0f; + plvec->emplace_back(pl4); // Camera actor pCameraActor = new CameraActor(this); // UI elements diff --git a/Chapter06/Renderer.cpp b/Chapter06/Renderer.cpp index 00e7bd13..72674ad2 100644 --- a/Chapter06/Renderer.cpp +++ b/Chapter06/Renderer.cpp @@ -75,8 +75,7 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) void Renderer::Shutdown() { delete pSpriteVerts; - // NOTE: Shaders are unloaded elsewhere - delete pCurrentShader; + pSpriteVerts = nullptr; SDL_GL_DeleteContext(mContext); SDL_DestroyWindow(pWindow); } @@ -328,4 +327,16 @@ void Renderer::SetLightUniforms(Shader* shader) shader->SetVectorUniform("uDirLight.mDirection", mDirLight.mDirection); shader->SetVectorUniform("uDirLight.mDiffuseColor", mDirLight.mDiffuseColor); shader->SetVectorUniform("uDirLight.mSpecColor", mDirLight.mSpecColor); + // Point lights + for (int i = 0; i < mPointLights.size(); i++) + { + std::string intstring = std::to_string(i); + shader->SetVectorUniform(((std::string)"uPointLights[" + intstring + "].mWorldPos").c_str(), mPointLights[i].mWorldPos); + shader->SetVectorUniform(((std::string)"uPointLights[" + intstring + "].mDiffuseColor").c_str(), mPointLights[i].mDiffuseColor); + shader->SetVectorUniform(((std::string)"uPointLights[" + intstring + "].mSpecColor").c_str(), mPointLights[i].mSpecColor); + shader->SetFloatUniform(((std::string)"uPointLights[" + intstring + "].mInnerRadius").c_str(), mPointLights[i].mInnerRadius); + shader->SetFloatUniform(((std::string)"uPointLights[" + intstring + "].mOuterRadius").c_str(), mPointLights[i].mOuterRadius); + } + // Pass the size of the array to the shader + shader->SetIntUniform("uNumPointLights", mPointLights.size()); } \ No newline at end of file diff --git a/Chapter06/Renderer.h b/Chapter06/Renderer.h index 4fa8ee85..e74ee2fd 100644 --- a/Chapter06/Renderer.h +++ b/Chapter06/Renderer.h @@ -23,6 +23,19 @@ struct DirectionalLight Vector3 mSpecColor; }; +struct PointLight +{ + // Position of light + Vector3 mWorldPos; + // Diffuse color + Vector3 mDiffuseColor; + // Specular color + Vector3 mSpecColor; + // Radius of the light + float mInnerRadius; + float mOuterRadius; +}; + class Renderer { public: @@ -42,6 +55,7 @@ class Renderer void SetViewMatrix(const Matrix4& view) { mView = view; } void SetAmbientLight(const Vector3& ambient) { mAmbientLight = ambient; } DirectionalLight& GetDirectionalLight() { return mDirLight; } + std::vector* GetPointLights() { return &mPointLights; } float GetScreenWidth() const { return mScreenWidth; } float GetScreenHeight() const { return mScreenHeight; } private: @@ -76,6 +90,7 @@ class Renderer // Lighting data Vector3 mAmbientLight; DirectionalLight mDirLight; + std::vector mPointLights = {}; // Window SDL_Window* pWindow; // OpenGL context diff --git a/Chapter06/Shader.cpp b/Chapter06/Shader.cpp index a9702108..3ca5f725 100644 --- a/Chapter06/Shader.cpp +++ b/Chapter06/Shader.cpp @@ -77,6 +77,13 @@ void Shader::SetFloatUniform(const char* name, float value) glUniform1f(loc, value); } +void Shader::SetIntUniform(const char* name, int value) +{ + GLuint loc = glGetUniformLocation(mShaderProgram, name); + // Send the float data + glUniform1i(loc, value); +} + bool Shader::CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader) { // Open file diff --git a/Chapter06/Shader.h b/Chapter06/Shader.h index f9c5e33e..78bb8533 100644 --- a/Chapter06/Shader.h +++ b/Chapter06/Shader.h @@ -27,6 +27,8 @@ class Shader void SetVectorUniform(const char* name, const Vector3& vector); // Sets a float uniform void SetFloatUniform(const char* name, float value); + // Sets a int uniform + void SetIntUniform(const char* name, int value); private: // Tries to compile the specified shader bool CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader); diff --git a/Chapter06/Shaders/Phong.frag b/Chapter06/Shaders/Phong.frag index 081fa77e..0da5eb6c 100644 --- a/Chapter06/Shaders/Phong.frag +++ b/Chapter06/Shaders/Phong.frag @@ -30,6 +30,19 @@ struct DirectionalLight // Specular color vec3 mSpecColor; }; +// Create a struct for point light +struct PointLight +{ + // Position of light + vec3 mWorldPos; + // Diffuse color + vec3 mDiffuseColor; + // Specular color + vec3 mSpecColor; + // Radius of the light + float mInnerRadius; + float mOuterRadius; +}; // Uniforms for lighting // Camera position (in world space) uniform vec3 uCameraPos; @@ -39,26 +52,55 @@ uniform float uSpecPower; uniform vec3 uAmbientLight; // Directional Light uniform DirectionalLight uDirLight; +// Point Lights +uniform PointLight[4] uPointLights; +// Size of PointLight array +uniform int uNumPointLights; void main() { + vec4 output = texture(uTexture, fragTexCoord); // Surface normal vec3 N = normalize(fragNormal); - // Vector from surface to light - vec3 L = normalize(-uDirLight.mDirection); // Vector from surface to camera vec3 V = normalize(uCameraPos - fragWorldPos); +// Directional Light: + // Vector from surface to light + vec3 D_L = normalize(-uDirLight.mDirection); // Reflection of -L about N - vec3 R = normalize(reflect(-L, N)); + vec3 D_R = normalize(reflect(-D_L, N)); // Compute phong reflection - vec3 Phong = uAmbientLight; - float NdotL = dot(N, L); - if (NdotL > 0) + vec3 D_Phong = uAmbientLight; + float D_NdotL = dot(N, D_L); + if (D_NdotL > 0) + { + vec3 D_Diffuse = uDirLight.mDiffuseColor * D_NdotL; + vec3 D_Specular = uDirLight.mSpecColor * pow(max(0.0, dot(D_R, V)), uSpecPower); + D_Phong += D_Diffuse + D_Specular; + } + output *= vec4(D_Phong, 1.0f); +// Point Lights: + for(int i = 0; i < uNumPointLights; i++) { - vec3 Diffuse = uDirLight.mDiffuseColor * NdotL; - vec3 Specular = uDirLight.mSpecColor * pow(max(0.0, dot(R, V)), uSpecPower); - Phong += Diffuse + Specular; + // Vector from surface to light + vec3 P_L = normalize(uPointLights[i].mWorldPos - fragWorldPos); + // Reflection of -L about N + vec3 P_R = normalize(reflect(-P_L, N)); + // Compute phong reflection + vec3 P_Phong = vec3(1.0f, 1.0f, 1.0f); + float P_NdotL = dot(N, P_L); + if (P_NdotL > 0) + { + // Get the distance between the light and the world pos + float dist = distance(uPointLights[i].mWorldPos, fragWorldPos); + // Use smoothstep to compute value in range [0,1] between inner/outer radius + float intensity = smoothstep(uPointLights[i].mInnerRadius, uPointLights[i].mOuterRadius, dist); + vec3 P_Diffuse = mix(uPointLights[i].mDiffuseColor, vec3(0.0, 0.0, 0.0), intensity) * P_NdotL; + vec3 P_Specular = mix(uPointLights[i].mSpecColor, vec3(0.0, 0.0, 0.0), intensity) * pow(max(0.0, dot(P_R, V)), uSpecPower); + P_Phong += P_Diffuse + P_Specular; + output *= vec4(P_Phong, 1.0f); + } } // Final color is texture color times phong light (alpha = 1) - outColor = texture(uTexture, fragTexCoord) * vec4(Phong, 1.0f); + outColor = output; } \ No newline at end of file From 17dfd9b4d8f0f45f4a900a491555843b423eadc3 Mon Sep 17 00:00:00 2001 From: bobnone Date: Fri, 20 May 2022 12:59:02 -0500 Subject: [PATCH 6/6] Finished 7.1 --- Chapter07/Actor.cpp | 40 +++---- Chapter07/Actor.h | 21 ++-- Chapter07/AudioComponent.cpp | 20 ++-- Chapter07/AudioComponent.h | 2 - Chapter07/AudioSystem.cpp | 42 +++----- Chapter07/AudioSystem.h | 16 +-- Chapter07/CameraActor.cpp | 23 ++-- Chapter07/CameraActor.h | 8 +- Chapter07/CircleComponent.cpp | 13 +-- Chapter07/CircleComponent.h | 4 +- Chapter07/Component.cpp | 10 +- Chapter07/Component.h | 8 +- Chapter07/Game.cpp | 145 ++++++++++++-------------- Chapter07/Game.h | 21 ++-- Chapter07/Game.vcxproj | 26 ++--- Chapter07/Main.cpp | 2 +- Chapter07/Math.cpp | 44 ++------ Chapter07/Math.h | 173 ++++--------------------------- Chapter07/Mesh.cpp | 35 ++----- Chapter07/Mesh.h | 4 +- Chapter07/MeshComponent.cpp | 22 ++-- Chapter07/MeshComponent.h | 8 +- Chapter07/MoveComponent.cpp | 19 ++-- Chapter07/MoveComponent.h | 5 +- Chapter07/PlaneActor.cpp | 5 +- Chapter07/PlaneActor.h | 2 +- Chapter07/Renderer.cpp | 111 +++++++------------- Chapter07/Renderer.h | 27 +---- Chapter07/Shader.cpp | 33 +----- Chapter07/Shader.h | 7 +- Chapter07/Shaders/BasicMesh.frag | 4 +- Chapter07/Shaders/BasicMesh.vert | 5 +- Chapter07/Shaders/Phong.frag | 9 +- Chapter07/Shaders/Phong.vert | 6 +- Chapter07/Shaders/Sprite.frag | 4 +- Chapter07/Shaders/Sprite.vert | 5 +- Chapter07/SoundEvent.cpp | 50 ++++----- Chapter07/SoundEvent.h | 4 +- Chapter07/SpriteComponent.cpp | 32 ++---- Chapter07/SpriteComponent.h | 8 +- Chapter07/Texture.cpp | 23 +--- Chapter07/Texture.h | 5 +- Chapter07/VertexArray.cpp | 16 +-- Chapter07/VertexArray.h | 4 +- TODO.txt | 8 +- 45 files changed, 332 insertions(+), 747 deletions(-) diff --git a/Chapter07/Actor.cpp b/Chapter07/Actor.cpp index b3715cca..50680410 100644 --- a/Chapter07/Actor.cpp +++ b/Chapter07/Actor.cpp @@ -11,20 +11,14 @@ #include "Component.h" #include -Actor::Actor(Game* game) - :mState(EActive) - ,mPosition(Vector3::Zero) - ,mRotation(Quaternion::Identity) - ,mScale(1.0f) - ,mGame(game) - ,mRecomputeWorldTransform(true) +Actor::Actor(Game* game): mState(EActive), mPosition(Vector3::Zero), mOldPosition(Vector3::Zero), mVelocity(Vector3::Zero), mRotation(Quaternion::Identity), mScale(1.0f), pGame(game), mRecomputeWorldTransform(true) { - mGame->AddActor(this); + pGame->AddActor(this); } Actor::~Actor() { - mGame->RemoveActor(this); + pGame->RemoveActor(this); // Need to delete components // Because ~Component calls RemoveComponent, need a different style loop while (!mComponents.empty()) @@ -38,17 +32,15 @@ void Actor::Update(float deltaTime) if (mState == EActive) { ComputeWorldTransform(); - UpdateComponents(deltaTime); UpdateActor(deltaTime); - ComputeWorldTransform(); } } void Actor::UpdateComponents(float deltaTime) { - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->Update(deltaTime); } @@ -56,6 +48,14 @@ void Actor::UpdateComponents(float deltaTime) void Actor::UpdateActor(float deltaTime) { + if (mPosition != mOldPosition) + { + // NOTE: Velocity is change in position/time + mVelocity.x = (mPosition - mOldPosition).x / deltaTime; + mVelocity.y = (mPosition - mOldPosition).y / deltaTime; + mVelocity.z = (mPosition - mOldPosition).z / deltaTime; + mOldPosition = mPosition; + } } void Actor::ProcessInput(const uint8_t* keyState) @@ -63,11 +63,10 @@ void Actor::ProcessInput(const uint8_t* keyState) if (mState == EActive) { // First process input for components - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->ProcessInput(keyState); } - ActorInput(keyState); } } @@ -85,9 +84,8 @@ void Actor::ComputeWorldTransform() mWorldTransform = Matrix4::CreateScale(mScale); mWorldTransform *= Matrix4::CreateFromQuaternion(mRotation); mWorldTransform *= Matrix4::CreateTranslation(mPosition); - // Inform components world transform updated - for (auto comp : mComponents) + for (auto comp: mComponents) { comp->OnUpdateWorldTransform(); } @@ -96,20 +94,16 @@ void Actor::ComputeWorldTransform() void Actor::AddComponent(Component* component) { - // Find the insertion point in the sorted vector - // (The first element with a order higher than me) + // Find the insertion point in the sorted vector (The first element with a order higher than me) int myOrder = component->GetUpdateOrder(); auto iter = mComponents.begin(); - for (; - iter != mComponents.end(); - ++iter) + for (; iter != mComponents.end(); ++iter) { if (myOrder < (*iter)->GetUpdateOrder()) { break; } } - // Inserts element before position of iterator mComponents.insert(iter, component); } @@ -121,4 +115,4 @@ void Actor::RemoveComponent(Component* component) { mComponents.erase(iter); } -} +} \ No newline at end of file diff --git a/Chapter07/Actor.h b/Chapter07/Actor.h index 05d6b1b6..953b70aa 100644 --- a/Chapter07/Actor.h +++ b/Chapter07/Actor.h @@ -20,22 +20,18 @@ class Actor EPaused, EDead }; - Actor(class Game* game); virtual ~Actor(); - // Update function called from Game (not overridable) void Update(float deltaTime); // Updates all the components attached to the actor (not overridable) void UpdateComponents(float deltaTime); // Any actor-specific update code (overridable) virtual void UpdateActor(float deltaTime); - // ProcessInput function called from Game (not overridable) void ProcessInput(const uint8_t* keyState); // Any actor-specific input code (overridable) virtual void ActorInput(const uint8_t* keyState); - // Getters/setters const Vector3& GetPosition() const { return mPosition; } void SetPosition(const Vector3& pos) { mPosition = pos; mRecomputeWorldTransform = true; } @@ -43,32 +39,27 @@ class Actor void SetScale(float scale) { mScale = scale; mRecomputeWorldTransform = true; } const Quaternion& GetRotation() const { return mRotation; } void SetRotation(const Quaternion& rotation) { mRotation = rotation; mRecomputeWorldTransform = true; } - void ComputeWorldTransform(); const Matrix4& GetWorldTransform() const { return mWorldTransform; } - Vector3 GetForward() const { return Vector3::Transform(Vector3::UnitX, mRotation); } - + Vector3 GetVelocity() const { return mVelocity; } State GetState() const { return mState; } void SetState(State state) { mState = state; } - - class Game* GetGame() { return mGame; } - - + class Game* GetGame() { return pGame; } // Add/remove components void AddComponent(class Component* component); void RemoveComponent(class Component* component); private: // Actor's state State mState; - // Transform Matrix4 mWorldTransform; Vector3 mPosition; + Vector3 mOldPosition; + Vector3 mVelocity; Quaternion mRotation; float mScale; bool mRecomputeWorldTransform; - std::vector mComponents; - class Game* mGame; -}; + class Game* pGame; +}; \ No newline at end of file diff --git a/Chapter07/AudioComponent.cpp b/Chapter07/AudioComponent.cpp index 3131b08b..eab56550 100644 --- a/Chapter07/AudioComponent.cpp +++ b/Chapter07/AudioComponent.cpp @@ -11,8 +11,7 @@ #include "Game.h" #include "AudioSystem.h" -AudioComponent::AudioComponent(Actor* owner, int updateOrder) - :Component(owner, updateOrder) +AudioComponent::AudioComponent(Actor* owner, int updateOrder): Component(owner, updateOrder) { } @@ -24,7 +23,6 @@ AudioComponent::~AudioComponent() void AudioComponent::Update(float deltaTime) { Component::Update(deltaTime); - // Remove invalid 2D events auto iter = mEvents2D.begin(); while (iter != mEvents2D.end()) @@ -38,7 +36,6 @@ void AudioComponent::Update(float deltaTime) ++iter; } } - // Remove invalid 3D events iter = mEvents3D.begin(); while (iter != mEvents3D.end()) @@ -57,25 +54,24 @@ void AudioComponent::Update(float deltaTime) void AudioComponent::OnUpdateWorldTransform() { // Update 3D events' world transforms - Matrix4 world = mOwner->GetWorldTransform(); - for (auto& event : mEvents3D) + for (auto& event: mEvents3D) { if (event.IsValid()) { - event.Set3DAttributes(world); + event.Set3DAttributes(pOwner->GetWorldTransform(), pOwner->GetVelocity()); } } } SoundEvent AudioComponent::PlayEvent(const std::string& name) { - SoundEvent e = mOwner->GetGame()->GetAudioSystem()->PlayEvent(name); + SoundEvent e = pOwner->GetGame()->GetAudioSystem()->PlayEvent(name); // Is this 2D or 3D? if (e.Is3D()) { mEvents3D.emplace_back(e); // Set initial 3D attributes - e.Set3DAttributes(mOwner->GetWorldTransform()); + e.Set3DAttributes(pOwner->GetWorldTransform(), pOwner->GetVelocity()); } else { @@ -87,15 +83,15 @@ SoundEvent AudioComponent::PlayEvent(const std::string& name) void AudioComponent::StopAllEvents() { // Stop all sounds - for (auto& e : mEvents2D) + for (auto& e: mEvents2D) { e.Stop(); } - for (auto& e : mEvents3D) + for (auto& e: mEvents3D) { e.Stop(); } // Clear events mEvents2D.clear(); mEvents3D.clear(); -} +} \ No newline at end of file diff --git a/Chapter07/AudioComponent.h b/Chapter07/AudioComponent.h index 8fdecd2d..76bbe2da 100644 --- a/Chapter07/AudioComponent.h +++ b/Chapter07/AudioComponent.h @@ -17,10 +17,8 @@ class AudioComponent : public Component public: AudioComponent(class Actor* owner, int updateOrder = 200); ~AudioComponent(); - void Update(float deltaTime) override; void OnUpdateWorldTransform() override; - SoundEvent PlayEvent(const std::string& name); void StopAllEvents(); private: diff --git a/Chapter07/AudioSystem.cpp b/Chapter07/AudioSystem.cpp index 73c5feff..6ae30de7 100644 --- a/Chapter07/AudioSystem.cpp +++ b/Chapter07/AudioSystem.cpp @@ -14,10 +14,7 @@ unsigned int AudioSystem::sNextID = 0; -AudioSystem::AudioSystem(Game* game) - :mGame(game) - ,mSystem(nullptr) - ,mLowLevelSystem(nullptr) +AudioSystem::AudioSystem(Game* game): pGame(game), pSystem(nullptr) { } @@ -32,18 +29,16 @@ bool AudioSystem::Initialize() FMOD_DEBUG_LEVEL_ERROR, // Log only errors FMOD_DEBUG_MODE_TTY // Output to stdout ); - // Create FMOD studio system object FMOD_RESULT result; - result = FMOD::Studio::System::create(&mSystem); + result = FMOD::Studio::System::create(&pSystem); if (result != FMOD_OK) { SDL_Log("Failed to create FMOD system: %s", FMOD_ErrorString(result)); return false; } - // Initialize FMOD studio system - result = mSystem->initialize( + result = pSystem->initialize( 512, // Max number of concurrent sounds FMOD_STUDIO_INIT_NORMAL, // Use default settings FMOD_INIT_NORMAL, // Use default settings @@ -54,14 +49,11 @@ bool AudioSystem::Initialize() SDL_Log("Failed to initialize FMOD system: %s", FMOD_ErrorString(result)); return false; } - - // Save the low-level system pointer - mSystem->getLowLevelSystem(&mLowLevelSystem); - + // Save the core system pointer + pSystem->getCoreSystem(&pCoreSystem); // Load the master banks (strings first) LoadBank("Assets/Master Bank.strings.bank"); LoadBank("Assets/Master Bank.bank"); - return true; } @@ -70,9 +62,9 @@ void AudioSystem::Shutdown() // Unload all banks UnloadAllBanks(); // Shutdown FMOD system - if (mSystem) + if (pSystem) { - mSystem->release(); + pSystem->release(); } } @@ -83,15 +75,13 @@ void AudioSystem::LoadBank(const std::string& name) { return; } - // Try to load bank FMOD::Studio::Bank* bank = nullptr; - FMOD_RESULT result = mSystem->loadBankFile( + FMOD_RESULT result = pSystem->loadBankFile( name.c_str(), // File name of bank FMOD_STUDIO_LOAD_BANK_NORMAL, // Normal loading &bank // Save pointer to bank ); - const int maxPathLength = 512; if (result == FMOD_OK) { @@ -146,7 +136,6 @@ void AudioSystem::UnloadBank(const std::string& name) { return; } - // First we need to remove all events from this bank FMOD::Studio::Bank* bank = iter->second; int numEvents = 0; @@ -193,7 +182,6 @@ void AudioSystem::UnloadBank(const std::string& name) } } } - // Unload sample data and bank bank->unloadSampleData(); bank->unload(); @@ -253,15 +241,13 @@ void AudioSystem::Update(float deltaTime) done.emplace_back(iter.first); } } - // Remove done event instances from map for (auto id : done) { mEventInstances.erase(id); } - // Update FMOD - mSystem->update(); + pSystem->update(); } namespace @@ -278,7 +264,7 @@ namespace } } -void AudioSystem::SetListener(const Matrix4& viewMatrix) +void AudioSystem::SetListener(const Matrix4& viewMatrix, const Vector3& velocity) { // Invert the view matrix to get the correct vectors Matrix4 invView = viewMatrix; @@ -290,10 +276,10 @@ void AudioSystem::SetListener(const Matrix4& viewMatrix) listener.forward = VecToFMOD(invView.GetZAxis()); // In the inverted view, second row is up listener.up = VecToFMOD(invView.GetYAxis()); - // Set velocity to zero (fix if using Doppler effect) - listener.velocity = {0.0f, 0.0f, 0.0f}; + // Set velocity + listener.velocity = VecToFMOD(velocity); // Send to FMOD - mSystem->setListenerAttributes(0, &listener); + pSystem->setListenerAttributes(0, &listener); } float AudioSystem::GetBusVolume(const std::string& name) const @@ -345,4 +331,4 @@ FMOD::Studio::EventInstance* AudioSystem::GetEventInstance(unsigned int id) event = iter->second; } return event; -} +} \ No newline at end of file diff --git a/Chapter07/AudioSystem.h b/Chapter07/AudioSystem.h index 1e7398ef..2ff757a7 100644 --- a/Chapter07/AudioSystem.h +++ b/Chapter07/AudioSystem.h @@ -31,21 +31,16 @@ class AudioSystem public: AudioSystem(class Game* game); ~AudioSystem(); - bool Initialize(); void Shutdown(); - // Load/unload banks void LoadBank(const std::string& name); void UnloadBank(const std::string& name); void UnloadAllBanks(); - SoundEvent PlayEvent(const std::string& name); - void Update(float deltaTime); - // For positional audio - void SetListener(const Matrix4& viewMatrix); + void SetListener(const Matrix4& viewMatrix, const Vector3& velocity = Vector3::Zero); // Control buses float GetBusVolume(const std::string& name) const; bool GetBusPaused(const std::string& name) const; @@ -57,8 +52,7 @@ class AudioSystem private: // Tracks the next ID to use for event instances static unsigned int sNextID; - - class Game* mGame; + class Game* pGame; // Map of loaded banks std::unordered_map mBanks; // Map of event name to EventDescription @@ -68,7 +62,7 @@ class AudioSystem // Map of buses std::unordered_map mBuses; // FMOD studio system - FMOD::Studio::System* mSystem; - // FMOD Low-level system (in case needed) - FMOD::System* mLowLevelSystem; + FMOD::Studio::System* pSystem; + // FMOD core system (in case needed) + FMOD::System* pCoreSystem; }; \ No newline at end of file diff --git a/Chapter07/CameraActor.cpp b/Chapter07/CameraActor.cpp index ec43a95f..32d910b9 100644 --- a/Chapter07/CameraActor.cpp +++ b/Chapter07/CameraActor.cpp @@ -14,29 +14,26 @@ #include "Game.h" #include "AudioComponent.h" -CameraActor::CameraActor(Game* game) - :Actor(game) +CameraActor::CameraActor(Game* game): Actor(game) { - mMoveComp = new MoveComponent(this); - mAudioComp = new AudioComponent(this); + pMoveComp = new MoveComponent(this); + pAudioComp = new AudioComponent(this); mLastFootstep = 0.0f; - mFootstep = mAudioComp->PlayEvent("event:/Footstep"); + mFootstep = pAudioComp->PlayEvent("event:/Footstep"); mFootstep.SetPaused(true); } void CameraActor::UpdateActor(float deltaTime) { Actor::UpdateActor(deltaTime); - // Play the footstep if we're moving and haven't recently mLastFootstep -= deltaTime; - if (!Math::NearZero(mMoveComp->GetForwardSpeed()) && mLastFootstep <= 0.0f) + if (!Math::NearZero(pMoveComp->GetForwardSpeed()) && mLastFootstep <= 0.0f) { mFootstep.SetPaused(false); mFootstep.Restart(); mLastFootstep = 0.5f; } - // Compute new camera from this actor Vector3 cameraPos = GetPosition(); Vector3 target = GetPosition() + GetForward() * 100.0f; @@ -67,15 +64,13 @@ void CameraActor::ActorInput(const uint8_t* keys) { angularSpeed += Math::TwoPi; } - - mMoveComp->SetForwardSpeed(forwardSpeed); - mMoveComp->SetAngularSpeed(angularSpeed); + pMoveComp->SetForwardSpeed(forwardSpeed); + pMoveComp->SetAngularSpeed(angularSpeed); } void CameraActor::SetFootstepSurface(float value) { - // Pause here because the way I setup the parameter in FMOD - // changing it will play a footstep + // Pause here because the way I setup the parameter in FMOD changing it will play a footstep mFootstep.SetPaused(true); mFootstep.SetParameter("Surface", value); -} +} \ No newline at end of file diff --git a/Chapter07/CameraActor.h b/Chapter07/CameraActor.h index 7c95d106..502f9b14 100644 --- a/Chapter07/CameraActor.h +++ b/Chapter07/CameraActor.h @@ -10,18 +10,16 @@ #include "Actor.h" #include "SoundEvent.h" -class CameraActor : public Actor +class CameraActor: public Actor { public: CameraActor(class Game* game); - void UpdateActor(float deltaTime) override; void ActorInput(const uint8_t* keys) override; - void SetFootstepSurface(float value); private: - class MoveComponent* mMoveComp; - class AudioComponent* mAudioComp; + class MoveComponent* pMoveComp; + class AudioComponent* pAudioComp; SoundEvent mFootstep; float mLastFootstep; }; \ No newline at end of file diff --git a/Chapter07/CircleComponent.cpp b/Chapter07/CircleComponent.cpp index 4e40d109..f57bdd8a 100644 --- a/Chapter07/CircleComponent.cpp +++ b/Chapter07/CircleComponent.cpp @@ -9,21 +9,18 @@ #include "CircleComponent.h" #include "Actor.h" -CircleComponent::CircleComponent(class Actor* owner) -:Component(owner) -,mRadius(0.0f) +CircleComponent::CircleComponent(class Actor* owner): Component(owner), mRadius(0.0f) { - } const Vector3& CircleComponent::GetCenter() const { - return mOwner->GetPosition(); + return pOwner->GetPosition(); } float CircleComponent::GetRadius() const { - return mOwner->GetScale() * mRadius; + return pOwner->GetScale() * mRadius; } bool Intersect(const CircleComponent& a, const CircleComponent& b) @@ -31,10 +28,8 @@ bool Intersect(const CircleComponent& a, const CircleComponent& b) // Calculate distance squared Vector3 diff = a.GetCenter() - b.GetCenter(); float distSq = diff.LengthSq(); - // Calculate sum of radii squared float radiiSq = a.GetRadius() + b.GetRadius(); radiiSq *= radiiSq; - return distSq <= radiiSq; -} +} \ No newline at end of file diff --git a/Chapter07/CircleComponent.h b/Chapter07/CircleComponent.h index 61c63ba9..57dda8ec 100644 --- a/Chapter07/CircleComponent.h +++ b/Chapter07/CircleComponent.h @@ -14,13 +14,11 @@ class CircleComponent : public Component { public: CircleComponent(class Actor* owner); - void SetRadius(float radius) { mRadius = radius; } float GetRadius() const; - const Vector3& GetCenter() const; private: float mRadius; }; -bool Intersect(const CircleComponent& a, const CircleComponent& b); +bool Intersect(const CircleComponent& a, const CircleComponent& b); \ No newline at end of file diff --git a/Chapter07/Component.cpp b/Chapter07/Component.cpp index c4ed432d..5446d684 100644 --- a/Chapter07/Component.cpp +++ b/Chapter07/Component.cpp @@ -9,19 +9,17 @@ #include "Component.h" #include "Actor.h" -Component::Component(Actor* owner, int updateOrder) - :mOwner(owner) - ,mUpdateOrder(updateOrder) +Component::Component(Actor* owner, int updateOrder): pOwner(owner), mUpdateOrder(updateOrder) { // Add to actor's vector of components - mOwner->AddComponent(this); + pOwner->AddComponent(this); } Component::~Component() { - mOwner->RemoveComponent(this); + pOwner->RemoveComponent(this); } void Component::Update(float deltaTime) { -} +} \ No newline at end of file diff --git a/Chapter07/Component.h b/Chapter07/Component.h index e2be424b..a72aa198 100644 --- a/Chapter07/Component.h +++ b/Chapter07/Component.h @@ -12,8 +12,7 @@ class Component { public: - // Constructor - // (the lower the update order, the earlier the component updates) + // Constructor (the lower the update order, the earlier the component updates) Component(class Actor* owner, int updateOrder = 100); // Destructor virtual ~Component(); @@ -23,11 +22,10 @@ class Component virtual void ProcessInput(const uint8_t* keyState) {} // Called when world transform changes virtual void OnUpdateWorldTransform() { } - int GetUpdateOrder() const { return mUpdateOrder; } protected: // Owning actor - class Actor* mOwner; + class Actor* pOwner; // Update order of component int mUpdateOrder; -}; +}; \ No newline at end of file diff --git a/Chapter07/Game.cpp b/Chapter07/Game.cpp index e2715eb9..5e7dd5bd 100644 --- a/Chapter07/Game.cpp +++ b/Chapter07/Game.cpp @@ -17,13 +17,8 @@ #include "PlaneActor.h" #include "AudioComponent.h" -Game::Game() -:mRenderer(nullptr) -,mAudioSystem(nullptr) -,mIsRunning(true) -,mUpdatingActors(false) +Game::Game(): pRenderer(nullptr), pAudioSystem(nullptr), mIsRunning(true), mUpdatingActors(false) { - } bool Game::Initialize() @@ -33,32 +28,27 @@ bool Game::Initialize() SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } - // Create the renderer - mRenderer = new Renderer(this); - if (!mRenderer->Initialize(1024.0f, 768.0f)) + pRenderer = new Renderer(this); + if (!pRenderer->Initialize(1024.0f, 768.0f)) { SDL_Log("Failed to initialize renderer"); - delete mRenderer; - mRenderer = nullptr; + delete pRenderer; + pRenderer = nullptr; return false; } - // Create the audio system - mAudioSystem = new AudioSystem(this); - if (!mAudioSystem->Initialize()) + pAudioSystem = new AudioSystem(this); + if (!pAudioSystem->Initialize()) { SDL_Log("Failed to initialize audio system"); - mAudioSystem->Shutdown(); - delete mAudioSystem; - mAudioSystem = nullptr; + pAudioSystem->Shutdown(); + delete pAudioSystem; + pAudioSystem = nullptr; return false; } - LoadData(); - mTicksCount = SDL_GetTicks(); - return true; } @@ -93,14 +83,12 @@ void Game::ProcessInput() break; } } - const Uint8* state = SDL_GetKeyboardState(NULL); if (state[SDL_SCANCODE_ESCAPE]) { mIsRunning = false; } - - for (auto actor : mActors) + for (auto actor: mActors) { actor->ProcessInput(state); } @@ -113,22 +101,22 @@ void Game::HandleKeyPress(int key) case '-': { // Reduce master volume - float volume = mAudioSystem->GetBusVolume("bus:/"); + float volume = pAudioSystem->GetBusVolume("bus:/"); volume = Math::Max(0.0f, volume - 0.1f); - mAudioSystem->SetBusVolume("bus:/", volume); + pAudioSystem->SetBusVolume("bus:/", volume); break; } case '=': { // Increase master volume - float volume = mAudioSystem->GetBusVolume("bus:/"); + float volume = pAudioSystem->GetBusVolume("bus:/"); volume = Math::Min(1.0f, volume + 0.1f); - mAudioSystem->SetBusVolume("bus:/", volume); + pAudioSystem->SetBusVolume("bus:/", volume); break; } case 'e': // Play explosion - mAudioSystem->PlayEvent("event:/Explosion2D"); + pAudioSystem->PlayEvent("event:/Explosion2D"); break; case 'm': // Toggle music pause state @@ -138,7 +126,7 @@ void Game::HandleKeyPress(int key) // Stop or start reverb snapshot if (!mReverbSnap.IsValid()) { - mReverbSnap = mAudioSystem->PlayEvent("snapshot:/WithReverb"); + mReverbSnap = pAudioSystem->PlayEvent("snapshot:/WithReverb"); } else { @@ -147,11 +135,11 @@ void Game::HandleKeyPress(int key) break; case '1': // Set default footstep surface - mCameraActor->SetFootstepSurface(0.0f); + pCameraActor->SetFootstepSurface(0.0f); break; case '2': // Set grass footstep surface - mCameraActor->SetFootstepSurface(0.5f); + pCameraActor->SetFootstepSurface(0.5f); break; default: break; @@ -162,55 +150,64 @@ void Game::UpdateGame() { // Compute delta time // Wait until 16ms has elapsed since last frame - while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)) - ; - + while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)); float deltaTime = (SDL_GetTicks() - mTicksCount) / 1000.0f; if (deltaTime > 0.05f) { deltaTime = 0.05f; } mTicksCount = SDL_GetTicks(); - - // Update all actors +// Update all actors: mUpdatingActors = true; - for (auto actor : mActors) + // Update custom Sphere actor + Vector3 pos = pSphereActor->GetPosition(); + if(mDirection && (pos.y >= -1000)) + { + pos.y -= 5; + } + else if(!mDirection && pos.y <= 1000) + { + pos.y += 5; + } + else + { + mDirection = !mDirection; + } + pSphereActor->SetPosition(pos); + // Update the normal/alive actors + for (auto actor: mActors) { actor->Update(deltaTime); } mUpdatingActors = false; - // Move any pending actors to mActors - for (auto pending : mPendingActors) + for (auto pending: mPendingActors) { pending->ComputeWorldTransform(); mActors.emplace_back(pending); } mPendingActors.clear(); - // Add any dead actors to a temp vector std::vector deadActors; - for (auto actor : mActors) + for (auto actor: mActors) { if (actor->GetState() == Actor::EDead) { deadActors.emplace_back(actor); } } - // Delete dead actors (which removes them from mActors) - for (auto actor : deadActors) + for (auto actor: deadActors) { delete actor; } - // Update audio system - mAudioSystem->Update(deltaTime); + pAudioSystem->Update(deltaTime); } void Game::GenerateOutput() { - mRenderer->Draw(); + pRenderer->Draw(); } void Game::LoadData() @@ -223,14 +220,12 @@ void Game::LoadData() q = Quaternion::Concatenate(q, Quaternion(Vector3::UnitZ, Math::Pi + Math::Pi / 4.0f)); a->SetRotation(q); MeshComponent* mc = new MeshComponent(a); - mc->SetMesh(mRenderer->GetMesh("Assets/Cube.gpmesh")); - + mc->SetMesh(pRenderer->GetMesh("Assets/Cube.gpmesh")); a = new Actor(this); a->SetPosition(Vector3(200.0f, -75.0f, 0.0f)); a->SetScale(3.0f); mc = new MeshComponent(a); - mc->SetMesh(mRenderer->GetMesh("Assets/Sphere.gpmesh")); - + mc->SetMesh(pRenderer->GetMesh("Assets/Sphere.gpmesh")); // Setup floor const float start = -1250.0f; const float size = 250.0f; @@ -242,7 +237,6 @@ void Game::LoadData() a->SetPosition(Vector3(start + i * size, start + j * size, -100.0f)); } } - // Left/right walls q = Quaternion(Vector3::UnitX, Math::PiOver2); for (int i = 0; i < 10; i++) @@ -250,12 +244,10 @@ void Game::LoadData() a = new PlaneActor(this); a->SetPosition(Vector3(start + i * size, start - size, 0.0f)); a->SetRotation(q); - a = new PlaneActor(this); a->SetPosition(Vector3(start + i * size, -start + size, 0.0f)); a->SetRotation(q); } - q = Quaternion::Concatenate(q, Quaternion(Vector3::UnitZ, Math::PiOver2)); // Forward/back walls for (int i = 0; i < 10; i++) @@ -263,45 +255,38 @@ void Game::LoadData() a = new PlaneActor(this); a->SetPosition(Vector3(start - size, start + i * size, 0.0f)); a->SetRotation(q); - a = new PlaneActor(this); a->SetPosition(Vector3(-start + size, start + i * size, 0.0f)); a->SetRotation(q); } - // Setup lights - mRenderer->SetAmbientLight(Vector3(0.2f, 0.2f, 0.2f)); - DirectionalLight& dir = mRenderer->GetDirectionalLight(); + pRenderer->SetAmbientLight(Vector3(0.2f, 0.2f, 0.2f)); + DirectionalLight& dir = pRenderer->GetDirectionalLight(); dir.mDirection = Vector3(0.0f, -0.707f, -0.707f); dir.mDiffuseColor = Vector3(0.78f, 0.88f, 1.0f); dir.mSpecColor = Vector3(0.8f, 0.8f, 0.8f); - // Camera actor - mCameraActor = new CameraActor(this); - + pCameraActor = new CameraActor(this); // UI elements a = new Actor(this); a->SetPosition(Vector3(-350.0f, -350.0f, 0.0f)); SpriteComponent* sc = new SpriteComponent(a); - sc->SetTexture(mRenderer->GetTexture("Assets/HealthBar.png")); - + sc->SetTexture(pRenderer->GetTexture("Assets/HealthBar.png")); a = new Actor(this); a->SetPosition(Vector3(375.0f, -275.0f, 0.0f)); a->SetScale(0.75f); sc = new SpriteComponent(a); - sc->SetTexture(mRenderer->GetTexture("Assets/Radar.png")); - + sc->SetTexture(pRenderer->GetTexture("Assets/Radar.png")); // Create spheres with audio components playing different sounds - a = new Actor(this); - a->SetPosition(Vector3(500.0f, -75.0f, 0.0f)); - a->SetScale(1.0f); - mc = new MeshComponent(a); - mc->SetMesh(mRenderer->GetMesh("Assets/Sphere.gpmesh")); - AudioComponent* ac = new AudioComponent(a); + pSphereActor = new Actor(this); + pSphereActor->SetPosition(Vector3(500.0f, -75.0f, 0.0f)); + pSphereActor->SetScale(1.0f); + mc = new MeshComponent(pSphereActor); + mc->SetMesh(pRenderer->GetMesh("Assets/Sphere.gpmesh")); + AudioComponent* ac = new AudioComponent(pSphereActor); ac->PlayEvent("event:/FireLoop"); - // Start music - mMusicEvent = mAudioSystem->PlayEvent("event:/Music"); + mMusicEvent = pAudioSystem->PlayEvent("event:/Music"); } void Game::UnloadData() @@ -312,23 +297,22 @@ void Game::UnloadData() { delete mActors.back(); } - - if (mRenderer) + if (pRenderer) { - mRenderer->UnloadData(); + pRenderer->UnloadData(); } } void Game::Shutdown() { UnloadData(); - if (mRenderer) + if (pRenderer) { - mRenderer->Shutdown(); + pRenderer->Shutdown(); } - if (mAudioSystem) + if (pAudioSystem) { - mAudioSystem->Shutdown(); + pAudioSystem->Shutdown(); } SDL_Quit(); } @@ -356,7 +340,6 @@ void Game::RemoveActor(Actor* actor) std::iter_swap(iter, mPendingActors.end() - 1); mPendingActors.pop_back(); } - // Is it in actors? iter = std::find(mActors.begin(), mActors.end(), actor); if (iter != mActors.end()) @@ -365,4 +348,4 @@ void Game::RemoveActor(Actor* actor) std::iter_swap(iter, mActors.end() - 1); mActors.pop_back(); } -} +} \ No newline at end of file diff --git a/Chapter07/Game.h b/Chapter07/Game.h index 12825f7c..91b76754 100644 --- a/Chapter07/Game.h +++ b/Chapter07/Game.h @@ -21,12 +21,10 @@ class Game bool Initialize(); void RunLoop(); void Shutdown(); - void AddActor(class Actor* actor); void RemoveActor(class Actor* actor); - - class Renderer* GetRenderer() { return mRenderer; } - class AudioSystem* GetAudioSystem() { return mAudioSystem; } + class Renderer* GetRenderer() { return pRenderer; } + class AudioSystem* GetAudioSystem() { return pAudioSystem; } private: void ProcessInput(); void HandleKeyPress(int key); @@ -34,22 +32,21 @@ class Game void GenerateOutput(); void LoadData(); void UnloadData(); - // All the actors in the game std::vector mActors; // Any pending actors std::vector mPendingActors; - - class Renderer* mRenderer; - class AudioSystem* mAudioSystem; - + // Pointer to a specific Sphere actor + class Actor* pSphereActor; + bool mDirection; + class Renderer* pRenderer; + class AudioSystem* pAudioSystem; Uint32 mTicksCount; bool mIsRunning; // Track if we're updating actors right now bool mUpdatingActors; - // Game-specific code - class CameraActor* mCameraActor; + class CameraActor* pCameraActor; SoundEvent mMusicEvent; SoundEvent mReverbSnap; -}; +}; \ No newline at end of file diff --git a/Chapter07/Game.vcxproj b/Chapter07/Game.vcxproj index e14fa8e5..dc5a0881 100644 --- a/Chapter07/Game.vcxproj +++ b/Chapter07/Game.vcxproj @@ -63,19 +63,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v143 Unicode Application false - v141 + v143 true Unicode @@ -102,23 +102,23 @@ Disabled WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true - ..\external\SDL\include;..\external\GLEW\include;..\external\SOIL\include;..\external\rapidjson\include;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\inc;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\lowlevel\inc;%(AdditionalIncludeDirectories) + ..\external\SDL\include;..\external\GLEW\include;..\external\SOIL\include;..\external\rapidjson\include;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\inc;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\inc;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\fsbank\inc;%(AdditionalIncludeDirectories) false Sync Console true - ..\external\SDL\lib\win\x86;..\external\GLEW\lib\win\x86;..\external\SOIL\lib\win\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\lowlevel\lib;%(AdditionalLibraryDirectories) + ..\external\SDL\lib\win\x86;..\external\GLEW\lib\win\x86;..\external\SOIL\lib\win\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\lib\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\fsbank\lib\x86;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_image.lib;glew32.lib;SOIL.lib;fmodL_vc.lib;fmodstudioL_vc.lib;%(AdditionalDependencies) /NODEFAULTLIB:msvcrt.lib %(AdditionalOptions) xcopy "$(ProjectDir)\..\external\SDL\lib\win\x86\*.dll" "$(OutDir)" /i /s /y xcopy "$(ProjectDir)\..\external\GLEW\lib\win\x86\*.dll" "$(OutDir)" /i /s /y -xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\lowlevel\lib\*.dll" "$(OutDir)" /i /s /y -xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib\*.dll" "$(OutDir)" /i /s /y - +xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\lib\x86\*.dll" "$(OutDir)" /i /s /y +xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib\x86\*.dll" "$(OutDir)" /i /s /y +xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\fsbank\lib\x86\*.dll" "$(OutDir)" /i /s /y @@ -130,7 +130,7 @@ xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studi true WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true - ..\external\SDL\include;..\external\GLEW\include;..\external\SOIL\include;..\external\rapidjson\include;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\inc;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\lowlevel\inc;%(AdditionalIncludeDirectories) + ..\external\SDL\include;..\external\GLEW\include;..\external\SOIL\include;..\external\rapidjson\include;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\inc;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\inc;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\fsbank\inc;%(AdditionalIncludeDirectories) false Sync @@ -139,15 +139,15 @@ xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studi true true true - ..\external\SDL\lib\win\x86;..\external\GLEW\lib\win\x86;..\external\SOIL\lib\win\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\lowlevel\lib;%(AdditionalLibraryDirectories) + ..\external\SDL\lib\win\x86;..\external\GLEW\lib\win\x86;..\external\SOIL\lib\win\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\lib\x86;C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\fsbank\lib\x86;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_image.lib;glew32.lib;SOIL.lib;fmodL_vc.lib;fmodstudioL_vc.lib;%(AdditionalDependencies) xcopy "$(ProjectDir)\..\external\SDL\lib\win\x86\*.dll" "$(OutDir)" /i /s /y xcopy "$(ProjectDir)\..\external\GLEW\lib\win\x86\*.dll" "$(OutDir)" /i /s /y -xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\lowlevel\lib\*.dll" "$(OutDir)" /i /s /y -xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib\*.dll" "$(OutDir)" /i /s /y - +xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\lib\x86\*.dll" "$(OutDir)" /i /s /y +xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\studio\lib\x86\*.dll" "$(OutDir)" /i /s /y +xcopy "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\fsbank\lib\x86\*.dll" "$(OutDir)" /i /s /y diff --git a/Chapter07/Main.cpp b/Chapter07/Main.cpp index 22ea0c69..625e0599 100644 --- a/Chapter07/Main.cpp +++ b/Chapter07/Main.cpp @@ -18,4 +18,4 @@ int main(int argc, char** argv) } game.Shutdown(); return 0; -} +} \ No newline at end of file diff --git a/Chapter07/Math.cpp b/Chapter07/Math.cpp index a16e7261..1435e4a9 100644 --- a/Chapter07/Math.cpp +++ b/Chapter07/Math.cpp @@ -39,7 +39,6 @@ static float m4Ident[4][4] = { 0.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }; - const Matrix4 Matrix4::Identity(m4Ident); const Quaternion Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f); @@ -56,12 +55,9 @@ Vector2 Vector2::Transform(const Vector2& vec, const Matrix3& mat, float w /*= 1 Vector3 Vector3::Transform(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/) { Vector3 retVal; - retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + - vec.z * mat.mat[2][0] + w * mat.mat[3][0]; - retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + - vec.z * mat.mat[2][1] + w * mat.mat[3][1]; - retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + - vec.z * mat.mat[2][2] + w * mat.mat[3][2]; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + vec.z * mat.mat[2][0] + w * mat.mat[3][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + vec.z * mat.mat[2][1] + w * mat.mat[3][1]; + retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + vec.z * mat.mat[2][2] + w * mat.mat[3][2]; //ignore w since we aren't returning a new value for it... return retVal; } @@ -70,14 +66,10 @@ Vector3 Vector3::Transform(const Vector3& vec, const Matrix4& mat, float w /*= 1 Vector3 Vector3::TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/) { Vector3 retVal; - retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + - vec.z * mat.mat[2][0] + w * mat.mat[3][0]; - retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + - vec.z * mat.mat[2][1] + w * mat.mat[3][1]; - retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + - vec.z * mat.mat[2][2] + w * mat.mat[3][2]; - float transformedW = vec.x * mat.mat[0][3] + vec.y * mat.mat[1][3] + - vec.z * mat.mat[2][3] + w * mat.mat[3][3]; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + vec.z * mat.mat[2][0] + w * mat.mat[3][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + vec.z * mat.mat[2][1] + w * mat.mat[3][1]; + retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + vec.z * mat.mat[2][2] + w * mat.mat[3][2]; + float transformedW = vec.x * mat.mat[0][3] + vec.y * mat.mat[1][3] + vec.z * mat.mat[2][3] + w * mat.mat[3][3]; if (!Math::NearZero(Math::Abs(transformedW))) { transformedW = 1.0f / transformedW; @@ -104,33 +96,28 @@ void Matrix4::Invert() float src[16]; float dst[16]; float det; - - // Transpose matrix +// Transpose matrix: // row 1 to col 1 src[0] = mat[0][0]; src[4] = mat[0][1]; src[8] = mat[0][2]; src[12] = mat[0][3]; - // row 2 to col 2 src[1] = mat[1][0]; src[5] = mat[1][1]; src[9] = mat[1][2]; src[13] = mat[1][3]; - // row 3 to col 3 src[2] = mat[2][0]; src[6] = mat[2][1]; src[10] = mat[2][2]; src[14] = mat[2][3]; - // row 4 to col 4 src[3] = mat[3][0]; src[7] = mat[3][1]; src[11] = mat[3][2]; src[15] = mat[3][3]; - - // Calculate cofactors +// Calculate cofactors: tmp[0] = src[10] * src[15]; tmp[1] = src[11] * src[14]; tmp[2] = src[9] * src[15]; @@ -143,7 +130,6 @@ void Matrix4::Invert() tmp[9] = src[10] * src[12]; tmp[10] = src[8] * src[13]; tmp[11] = src[9] * src[12]; - dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; @@ -160,7 +146,6 @@ void Matrix4::Invert() dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; - tmp[0] = src[2] * src[7]; tmp[1] = src[3] * src[6]; tmp[2] = src[1] * src[7]; @@ -173,7 +158,6 @@ void Matrix4::Invert() tmp[9] = src[2] * src[4]; tmp[10] = src[0] * src[5]; tmp[11] = src[1] * src[4]; - dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; @@ -190,17 +174,14 @@ void Matrix4::Invert() dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; - // Calculate determinant det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3]; - // Inverse of matrix is divided by determinant det = 1 / det; for (int j = 0; j < 16; j++) { dst[j] *= det; } - // Set it back for (int i = 0; i < 4; i++) { @@ -214,26 +195,21 @@ void Matrix4::Invert() Matrix4 Matrix4::CreateFromQuaternion(const class Quaternion& q) { float mat[4][4]; - mat[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z; mat[0][1] = 2.0f * q.x * q.y + 2.0f * q.w * q.z; mat[0][2] = 2.0f * q.x * q.z - 2.0f * q.w * q.y; mat[0][3] = 0.0f; - mat[1][0] = 2.0f * q.x * q.y - 2.0f * q.w * q.z; mat[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z; mat[1][2] = 2.0f * q.y * q.z + 2.0f * q.w * q.x; mat[1][3] = 0.0f; - mat[2][0] = 2.0f * q.x * q.z + 2.0f * q.w * q.y; mat[2][1] = 2.0f * q.y * q.z - 2.0f * q.w * q.x; mat[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y; mat[2][3] = 0.0f; - mat[3][0] = 0.0f; mat[3][1] = 0.0f; mat[3][2] = 0.0f; mat[3][3] = 1.0f; - return Matrix4(mat); -} +} \ No newline at end of file diff --git a/Chapter07/Math.h b/Chapter07/Math.h index 752963f1..44666a0d 100644 --- a/Chapter07/Math.h +++ b/Chapter07/Math.h @@ -24,12 +24,10 @@ namespace Math { return degrees * Pi / 180.0f; } - inline float ToDegrees(float radians) { return radians * 180.0f / Pi; } - inline bool NearZero(float val, float epsilon = 0.001f) { if (fabs(val) <= epsilon) @@ -41,70 +39,57 @@ namespace Math return false; } } - template T Max(const T& a, const T& b) { return (a < b ? b : a); } - template T Min(const T& a, const T& b) { return (a < b ? a : b); } - template T Clamp(const T& value, const T& lower, const T& upper) { return Min(upper, Max(lower, value)); } - inline float Abs(float value) { return fabs(value); } - inline float Cos(float angle) { return cosf(angle); } - inline float Sin(float angle) { return sinf(angle); } - inline float Tan(float angle) { return tanf(angle); } - inline float Acos(float value) { return acosf(value); } - inline float Atan2(float y, float x) { return atan2f(y, x); } - inline float Cot(float angle) { return 1.0f / Tan(angle); } - inline float Lerp(float a, float b, float f) { return a + f * (b - a); } - inline float Sqrt(float value) { return sqrtf(value); } - inline float Fmod(float numer, float denom) { return fmod(numer, denom); @@ -118,54 +103,41 @@ class Vector2 float x; float y; - Vector2() - :x(0.0f) - ,y(0.0f) + Vector2(): x(0.0f), y(0.0f) {} - - explicit Vector2(float inX, float inY) - :x(inX) - ,y(inY) + explicit Vector2(float inX, float inY): x(inX), y(inY) {} - // Set both components in one line void Set(float inX, float inY) { x = inX; y = inY; } - // Vector addition (a + b) friend Vector2 operator+(const Vector2& a, const Vector2& b) { return Vector2(a.x + b.x, a.y + b.y); } - // Vector subtraction (a - b) friend Vector2 operator-(const Vector2& a, const Vector2& b) { return Vector2(a.x - b.x, a.y - b.y); } - // Component-wise multiplication - // (a.x * b.x, ...) friend Vector2 operator*(const Vector2& a, const Vector2& b) { return Vector2(a.x * b.x, a.y * b.y); } - // Scalar multiplication friend Vector2 operator*(const Vector2& vec, float scalar) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar multiplication friend Vector2 operator*(float scalar, const Vector2& vec) { return Vector2(vec.x * scalar, vec.y * scalar); } - // Scalar *= Vector2& operator*=(float scalar) { @@ -173,7 +145,6 @@ class Vector2 y *= scalar; return *this; } - // Vector += Vector2& operator+=(const Vector2& right) { @@ -181,7 +152,6 @@ class Vector2 y += right.y; return *this; } - // Vector -= Vector2& operator-=(const Vector2& right) { @@ -189,19 +159,16 @@ class Vector2 y -= right.y; return *this; } - // Length squared of vector float LengthSq() const { return (x*x + y*y); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -209,7 +176,6 @@ class Vector2 x /= length; y /= length; } - // Normalize the provided vector static Vector2 Normalize(const Vector2& vec) { @@ -217,25 +183,21 @@ class Vector2 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector2& a, const Vector2& b) { return (a.x * b.x + a.y * b.y); } - // Lerp from A to B by f static Vector2 Lerp(const Vector2& a, const Vector2& b, float f) { return Vector2(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector2 Reflect(const Vector2& v, const Vector2& n) { return v - 2.0f * Vector2::Dot(v, n) * n; } - // Transform vector by matrix static Vector2 Transform(const Vector2& vec, const class Matrix3& mat, float w = 1.0f); @@ -254,24 +216,15 @@ class Vector3 float y; float z; - Vector3() - :x(0.0f) - ,y(0.0f) - ,z(0.0f) + Vector3(): x(0.0f), y(0.0f), z(0.0f) {} - - explicit Vector3(float inX, float inY, float inZ) - :x(inX) - ,y(inY) - ,z(inZ) + explicit Vector3(float inX, float inY, float inZ): x(inX), y(inY), z(inZ) {} - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&x); } - // Set all three components in one line void Set(float inX, float inY, float inZ) { @@ -279,37 +232,31 @@ class Vector3 y = inY; z = inZ; } - // Vector addition (a + b) friend Vector3 operator+(const Vector3& a, const Vector3& b) { return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); } - // Vector subtraction (a - b) friend Vector3 operator-(const Vector3& a, const Vector3& b) { return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); } - // Component-wise multiplication friend Vector3 operator*(const Vector3& left, const Vector3& right) { return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); } - // Scalar multiplication friend Vector3 operator*(const Vector3& vec, float scalar) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar multiplication friend Vector3 operator*(float scalar, const Vector3& vec) { return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); } - // Scalar *= Vector3& operator*=(float scalar) { @@ -318,7 +265,6 @@ class Vector3 z *= scalar; return *this; } - // Vector += Vector3& operator+=(const Vector3& right) { @@ -327,7 +273,6 @@ class Vector3 z += right.z; return *this; } - // Vector -= Vector3& operator-=(const Vector3& right) { @@ -336,19 +281,26 @@ class Vector3 z -= right.z; return *this; } - + // Vector == + bool operator==(const Vector3& right) + { + return ((x == right.x) && (y == right.y) && (z == right.z)); + } + // Vector != + bool operator!=(const Vector3& right) + { + return !((x == right.x) && (y == right.y) && (z == right.z)); + } // Length squared of vector float LengthSq() const { return (x*x + y*y + z*z); } - // Length of vector float Length() const { return (Math::Sqrt(LengthSq())); } - // Normalize this vector void Normalize() { @@ -357,7 +309,6 @@ class Vector3 y /= length; z /= length; } - // Normalize the provided vector static Vector3 Normalize(const Vector3& vec) { @@ -365,13 +316,11 @@ class Vector3 temp.Normalize(); return temp; } - // Dot product between two vectors (a dot b) static float Dot(const Vector3& a, const Vector3& b) { return (a.x * b.x + a.y * b.y + a.z * b.z); } - // Cross product between two vectors (a cross b) static Vector3 Cross(const Vector3& a, const Vector3& b) { @@ -381,23 +330,19 @@ class Vector3 temp.z = a.x * b.y - a.y * b.x; return temp; } - // Lerp from A to B by f static Vector3 Lerp(const Vector3& a, const Vector3& b, float f) { return Vector3(a + f * (b - a)); } - // Reflect V about (normalized) N static Vector3 Reflect(const Vector3& v, const Vector3& n) { return v - 2.0f * Vector3::Dot(v, n) * n; } - static Vector3 Transform(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); // This will transform the vector and renormalize the w component static Vector3 TransformWithPerspDiv(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); - // Transform a Vector3 by a quaternion static Vector3 Transform(const Vector3& v, const class Quaternion& q); @@ -422,18 +367,15 @@ class Matrix3 { *this = Matrix3::Identity; } - explicit Matrix3(float inMat[3][3]) { memcpy(mat, inMat, 9 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication friend Matrix3 operator*(const Matrix3& left, const Matrix3& right) { @@ -443,58 +385,47 @@ class Matrix3 left.mat[0][0] * right.mat[0][0] + left.mat[0][1] * right.mat[1][0] + left.mat[0][2] * right.mat[2][0]; - retVal.mat[0][1] = left.mat[0][0] * right.mat[0][1] + left.mat[0][1] * right.mat[1][1] + left.mat[0][2] * right.mat[2][1]; - retVal.mat[0][2] = left.mat[0][0] * right.mat[0][2] + left.mat[0][1] * right.mat[1][2] + left.mat[0][2] * right.mat[2][2]; - // row 1 retVal.mat[1][0] = left.mat[1][0] * right.mat[0][0] + left.mat[1][1] * right.mat[1][0] + left.mat[1][2] * right.mat[2][0]; - retVal.mat[1][1] = left.mat[1][0] * right.mat[0][1] + left.mat[1][1] * right.mat[1][1] + left.mat[1][2] * right.mat[2][1]; - retVal.mat[1][2] = left.mat[1][0] * right.mat[0][2] + left.mat[1][1] * right.mat[1][2] + left.mat[1][2] * right.mat[2][2]; - // row 2 retVal.mat[2][0] = left.mat[2][0] * right.mat[0][0] + left.mat[2][1] * right.mat[1][0] + left.mat[2][2] * right.mat[2][0]; - retVal.mat[2][1] = left.mat[2][0] * right.mat[0][1] + left.mat[2][1] * right.mat[1][1] + left.mat[2][2] * right.mat[2][1]; - retVal.mat[2][2] = left.mat[2][0] * right.mat[0][2] + left.mat[2][1] * right.mat[1][2] + left.mat[2][2] * right.mat[2][2]; - return retVal; } - Matrix3& operator*=(const Matrix3& right) { *this = *this * right; return *this; } - // Create a scale matrix with x and y scales static Matrix3 CreateScale(float xScale, float yScale) { @@ -506,18 +437,15 @@ class Matrix3 }; return Matrix3(temp); } - static Matrix3 CreateScale(const Vector2& scaleVector) { return CreateScale(scaleVector.x, scaleVector.y); } - // Create a scale matrix with a uniform factor static Matrix3 CreateScale(float scale) { return CreateScale(scale, scale); } - // Create a rotation matrix about the Z axis // theta is in radians static Matrix3 CreateRotation(float theta) @@ -530,7 +458,6 @@ class Matrix3 }; return Matrix3(temp); } - // Create a translation matrix (on the xy-plane) static Matrix3 CreateTranslation(const Vector2& trans) { @@ -556,18 +483,15 @@ class Matrix4 { *this = Matrix4::Identity; } - explicit Matrix4(float inMat[4][4]) { memcpy(mat, inMat, 16 * sizeof(float)); } - // Cast to a const float pointer const float* GetAsFloatPtr() const { return reinterpret_cast(&mat[0][0]); } - // Matrix multiplication (a * b) friend Matrix4 operator*(const Matrix4& a, const Matrix4& b) { @@ -578,136 +502,113 @@ class Matrix4 a.mat[0][1] * b.mat[1][0] + a.mat[0][2] * b.mat[2][0] + a.mat[0][3] * b.mat[3][0]; - retVal.mat[0][1] = a.mat[0][0] * b.mat[0][1] + a.mat[0][1] * b.mat[1][1] + a.mat[0][2] * b.mat[2][1] + a.mat[0][3] * b.mat[3][1]; - retVal.mat[0][2] = a.mat[0][0] * b.mat[0][2] + a.mat[0][1] * b.mat[1][2] + a.mat[0][2] * b.mat[2][2] + a.mat[0][3] * b.mat[3][2]; - retVal.mat[0][3] = a.mat[0][0] * b.mat[0][3] + a.mat[0][1] * b.mat[1][3] + a.mat[0][2] * b.mat[2][3] + a.mat[0][3] * b.mat[3][3]; - // row 1 retVal.mat[1][0] = a.mat[1][0] * b.mat[0][0] + a.mat[1][1] * b.mat[1][0] + a.mat[1][2] * b.mat[2][0] + a.mat[1][3] * b.mat[3][0]; - retVal.mat[1][1] = a.mat[1][0] * b.mat[0][1] + a.mat[1][1] * b.mat[1][1] + a.mat[1][2] * b.mat[2][1] + a.mat[1][3] * b.mat[3][1]; - retVal.mat[1][2] = a.mat[1][0] * b.mat[0][2] + a.mat[1][1] * b.mat[1][2] + a.mat[1][2] * b.mat[2][2] + a.mat[1][3] * b.mat[3][2]; - retVal.mat[1][3] = a.mat[1][0] * b.mat[0][3] + a.mat[1][1] * b.mat[1][3] + a.mat[1][2] * b.mat[2][3] + a.mat[1][3] * b.mat[3][3]; - // row 2 retVal.mat[2][0] = a.mat[2][0] * b.mat[0][0] + a.mat[2][1] * b.mat[1][0] + a.mat[2][2] * b.mat[2][0] + a.mat[2][3] * b.mat[3][0]; - retVal.mat[2][1] = a.mat[2][0] * b.mat[0][1] + a.mat[2][1] * b.mat[1][1] + a.mat[2][2] * b.mat[2][1] + a.mat[2][3] * b.mat[3][1]; - retVal.mat[2][2] = a.mat[2][0] * b.mat[0][2] + a.mat[2][1] * b.mat[1][2] + a.mat[2][2] * b.mat[2][2] + a.mat[2][3] * b.mat[3][2]; - retVal.mat[2][3] = a.mat[2][0] * b.mat[0][3] + a.mat[2][1] * b.mat[1][3] + a.mat[2][2] * b.mat[2][3] + a.mat[2][3] * b.mat[3][3]; - // row 3 retVal.mat[3][0] = a.mat[3][0] * b.mat[0][0] + a.mat[3][1] * b.mat[1][0] + a.mat[3][2] * b.mat[2][0] + a.mat[3][3] * b.mat[3][0]; - retVal.mat[3][1] = a.mat[3][0] * b.mat[0][1] + a.mat[3][1] * b.mat[1][1] + a.mat[3][2] * b.mat[2][1] + a.mat[3][3] * b.mat[3][1]; - retVal.mat[3][2] = a.mat[3][0] * b.mat[0][2] + a.mat[3][1] * b.mat[1][2] + a.mat[3][2] * b.mat[2][2] + a.mat[3][3] * b.mat[3][2]; - retVal.mat[3][3] = a.mat[3][0] * b.mat[0][3] + a.mat[3][1] * b.mat[1][3] + a.mat[3][2] * b.mat[2][3] + a.mat[3][3] * b.mat[3][3]; - return retVal; } - Matrix4& operator*=(const Matrix4& right) { *this = *this * right; return *this; } - // Invert the matrix - super slow void Invert(); - // Get the translation component of the matrix Vector3 GetTranslation() const { return Vector3(mat[3][0], mat[3][1], mat[3][2]); } - // Get the X axis of the matrix (forward) Vector3 GetXAxis() const { return Vector3::Normalize(Vector3(mat[0][0], mat[0][1], mat[0][2])); } - // Get the Y axis of the matrix (left) Vector3 GetYAxis() const { return Vector3::Normalize(Vector3(mat[1][0], mat[1][1], mat[1][2])); } - // Get the Z axis of the matrix (up) Vector3 GetZAxis() const { return Vector3::Normalize(Vector3(mat[2][0], mat[2][1], mat[2][2])); } - // Extract the scale component from the matrix Vector3 GetScale() const { @@ -717,7 +618,6 @@ class Matrix4 retVal.z = Vector3(mat[2][0], mat[2][1], mat[2][2]).Length(); return retVal; } - // Create a scale matrix with x, y, and z scales static Matrix4 CreateScale(float xScale, float yScale, float zScale) { @@ -730,18 +630,15 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateScale(const Vector3& scaleVector) { return CreateScale(scaleVector.x, scaleVector.y, scaleVector.z); } - // Create a scale matrix with a uniform factor static Matrix4 CreateScale(float scale) { return CreateScale(scale, scale, scale); } - // Rotation about x-axis static Matrix4 CreateRotationX(float theta) { @@ -754,7 +651,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about y-axis static Matrix4 CreateRotationY(float theta) { @@ -767,7 +663,6 @@ class Matrix4 }; return Matrix4(temp); } - // Rotation about z-axis static Matrix4 CreateRotationZ(float theta) { @@ -780,10 +675,8 @@ class Matrix4 }; return Matrix4(temp); } - // Create a rotation matrix from a quaternion static Matrix4 CreateFromQuaternion(const class Quaternion& q); - static Matrix4 CreateTranslation(const Vector3& trans) { float temp[4][4] = @@ -795,7 +688,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { Vector3 zaxis = Vector3::Normalize(target - eye); @@ -805,7 +697,6 @@ class Matrix4 trans.x = -Vector3::Dot(xaxis, eye); trans.y = -Vector3::Dot(yaxis, eye); trans.z = -Vector3::Dot(zaxis, eye); - float temp[4][4] = { { xaxis.x, yaxis.x, zaxis.x, 0.0f }, @@ -815,7 +706,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreateOrtho(float width, float height, float near, float far) { float temp[4][4] = @@ -827,7 +717,6 @@ class Matrix4 }; return Matrix4(temp); } - static Matrix4 CreatePerspectiveFOV(float fovY, float width, float height, float near, float far) { float yScale = Math::Cot(fovY / 2.0f); @@ -841,7 +730,6 @@ class Matrix4 }; return Matrix4(temp); } - // Create "Simple" View-Projection Matrix from Chapter 6 static Matrix4 CreateSimpleViewProj(float width, float height) { @@ -871,17 +759,13 @@ class Quaternion { *this = Quaternion::Identity; } - - // This directly sets the quaternion components -- - // don't use for axis/angle + // This directly sets the quaternion components -- don't use for axis/angle explicit Quaternion(float inX, float inY, float inZ, float inW) { Set(inX, inY, inZ, inW); } - - // Construct the quaternion from an axis and angle - // It is assumed that axis is already normalized, - // and the angle is in radians + /* Construct the quaternion from an axis and angle + NOTE: It is assumed that axis is already normalized, and the angle is in radians*/ explicit Quaternion(const Vector3& axis, float angle) { float scalar = Math::Sin(angle / 2.0f); @@ -890,7 +774,6 @@ class Quaternion z = axis.z * scalar; w = Math::Cos(angle / 2.0f); } - // Directly set the internal components void Set(float inX, float inY, float inZ, float inW) { @@ -899,24 +782,20 @@ class Quaternion z = inZ; w = inW; } - void Conjugate() { x *= -1.0f; y *= -1.0f; z *= -1.0f; } - float LengthSq() const { return (x*x + y*y + z*z + w*w); } - float Length() const { return Math::Sqrt(LengthSq()); } - void Normalize() { float length = Length(); @@ -925,7 +804,6 @@ class Quaternion z /= length; w /= length; } - // Normalize the provided quaternion static Quaternion Normalize(const Quaternion& q) { @@ -933,7 +811,6 @@ class Quaternion retVal.Normalize(); return retVal; } - // Linear interpolation static Quaternion Lerp(const Quaternion& a, const Quaternion& b, float f) { @@ -945,25 +822,20 @@ class Quaternion retVal.Normalize(); return retVal; } - static float Dot(const Quaternion& a, const Quaternion& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } - // Spherical Linear Interpolation static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float f) { float rawCosm = Quaternion::Dot(a, b); - float cosom = -rawCosm; if (rawCosm >= 0.0f) { cosom = rawCosm; } - float scale0, scale1; - if (cosom < 0.9999f) { const float omega = Math::Acos(cosom); @@ -973,17 +845,14 @@ class Quaternion } else { - // Use linear interpolation if the quaternions - // are collinear + // Use linear interpolation if the quaternions are collinear scale0 = 1.0f - f; scale1 = f; } - if (rawCosm < 0.0f) { scale1 = -scale1; } - Quaternion retVal; retVal.x = scale0 * a.x + scale1 * b.x; retVal.y = scale0 * a.y + scale1 * b.y; @@ -992,13 +861,11 @@ class Quaternion retVal.Normalize(); return retVal; } - // Concatenate // Rotate by q FOLLOWED BY p static Quaternion Concatenate(const Quaternion& q, const Quaternion& p) { Quaternion retVal; - // Vector component is: // ps * qv + qs * pv + pv x qv Vector3 qv(q.x, q.y, q.z); @@ -1007,11 +874,9 @@ class Quaternion retVal.x = newVec.x; retVal.y = newVec.y; retVal.z = newVec.z; - // Scalar component is: // ps * qs - pv . qv retVal.w = p.w * q.w - Vector3::Dot(pv, qv); - return retVal; } @@ -1030,4 +895,4 @@ namespace Color static const Vector3 LightBlue(0.68f, 0.85f, 0.9f); static const Vector3 LightPink(1.0f, 0.71f, 0.76f); static const Vector3 LightGreen(0.56f, 0.93f, 0.56f); -} +} \ No newline at end of file diff --git a/Chapter07/Mesh.cpp b/Chapter07/Mesh.cpp index 125ef961..f8e87ac9 100644 --- a/Chapter07/Mesh.cpp +++ b/Chapter07/Mesh.cpp @@ -16,10 +16,7 @@ #include #include "Math.h" -Mesh::Mesh() - :mVertexArray(nullptr) - ,mRadius(0.0f) - ,mSpecPower(100.0f) +Mesh::Mesh(): pVertexArray(nullptr), mRadius(0.0f), mSpecPower(100.0f) { } @@ -35,35 +32,27 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) SDL_Log("File not found: Mesh %s", fileName.c_str()); return false; } - std::stringstream fileStream; fileStream << file.rdbuf(); std::string contents = fileStream.str(); rapidjson::StringStream jsonStr(contents.c_str()); rapidjson::Document doc; doc.ParseStream(jsonStr); - if (!doc.IsObject()) { SDL_Log("Mesh %s is not valid json", fileName.c_str()); return false; } - int ver = doc["version"].GetInt(); - // Check the version if (ver != 1) { SDL_Log("Mesh %s not version 1", fileName.c_str()); return false; } - mShaderName = doc["shader"].GetString(); - - // Skip the vertex format/shader for now - // (This is changed in a later chapter's code) + // Skip the vertex format/shader for now (This is changed in a later chapter's code) size_t vertSize = 8; - // Load textures const rapidjson::Value& textures = doc["textures"]; if (!textures.IsArray() || textures.Size() < 1) @@ -71,9 +60,7 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) SDL_Log("Mesh %s has no textures, there should be at least one", fileName.c_str()); return false; } - mSpecPower = static_cast(doc["specularPower"].GetDouble()); - for (rapidjson::SizeType i = 0; i < textures.Size(); i++) { // Is this texture already loaded? @@ -91,7 +78,6 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) } mTextures.emplace_back(t); } - // Load in the vertices const rapidjson::Value& vertsJson = doc["vertices"]; if (!vertsJson.IsArray() || vertsJson.Size() < 1) @@ -99,7 +85,6 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) SDL_Log("Mesh %s has no vertices", fileName.c_str()); return false; } - std::vector vertices; vertices.reserve(vertsJson.Size() * vertSize); mRadius = 0.0f; @@ -112,20 +97,16 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) SDL_Log("Unexpected vertex format for %s", fileName.c_str()); return false; } - Vector3 pos(vert[0].GetDouble(), vert[1].GetDouble(), vert[2].GetDouble()); mRadius = Math::Max(mRadius, pos.LengthSq()); - // Add the floats for (rapidjson::SizeType i = 0; i < vert.Size(); i++) { vertices.emplace_back(static_cast(vert[i].GetDouble())); } } - // We were computing length squared earlier mRadius = Math::Sqrt(mRadius); - // Load in the indices const rapidjson::Value& indJson = doc["indices"]; if (!indJson.IsArray() || indJson.Size() < 1) @@ -133,7 +114,6 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) SDL_Log("Mesh %s has no indices", fileName.c_str()); return false; } - std::vector indices; indices.reserve(indJson.Size() * 3); for (rapidjson::SizeType i = 0; i < indJson.Size(); i++) @@ -144,22 +124,19 @@ bool Mesh::Load(const std::string& fileName, Renderer* renderer) SDL_Log("Invalid indices for %s", fileName.c_str()); return false; } - indices.emplace_back(ind[0].GetUint()); indices.emplace_back(ind[1].GetUint()); indices.emplace_back(ind[2].GetUint()); } - // Now create a vertex array - mVertexArray = new VertexArray(vertices.data(), static_cast(vertices.size()) / vertSize, - indices.data(), static_cast(indices.size())); + pVertexArray = new VertexArray(vertices.data(), static_cast(vertices.size()) / vertSize, indices.data(), static_cast(indices.size())); return true; } void Mesh::Unload() { - delete mVertexArray; - mVertexArray = nullptr; + delete pVertexArray; + pVertexArray = nullptr; } Texture* Mesh::GetTexture(size_t index) @@ -172,4 +149,4 @@ Texture* Mesh::GetTexture(size_t index) { return nullptr; } -} +} \ No newline at end of file diff --git a/Chapter07/Mesh.h b/Chapter07/Mesh.h index 3c1b5a3e..471f671b 100644 --- a/Chapter07/Mesh.h +++ b/Chapter07/Mesh.h @@ -19,7 +19,7 @@ class Mesh bool Load(const std::string& fileName, class Renderer* renderer); void Unload(); // Get the vertex array associated with this mesh - class VertexArray* GetVertexArray() { return mVertexArray; } + class VertexArray* GetVertexArray() { return pVertexArray; } // Get a texture from specified index class Texture* GetTexture(size_t index); // Get name of shader @@ -32,7 +32,7 @@ class Mesh // Textures associated with this mesh std::vector mTextures; // Vertex array associated with this mesh - class VertexArray* mVertexArray; + class VertexArray* pVertexArray; // Name of shader specified by mesh std::string mShaderName; // Stores object space bounding sphere radius diff --git a/Chapter07/MeshComponent.cpp b/Chapter07/MeshComponent.cpp index 1f4cbdb2..9020987d 100644 --- a/Chapter07/MeshComponent.cpp +++ b/Chapter07/MeshComponent.cpp @@ -15,38 +15,34 @@ #include "Texture.h" #include "VertexArray.h" -MeshComponent::MeshComponent(Actor* owner) - :Component(owner) - ,mMesh(nullptr) - ,mTextureIndex(0) +MeshComponent::MeshComponent(Actor* owner): Component(owner), pMesh(nullptr), mTextureIndex(0) { - mOwner->GetGame()->GetRenderer()->AddMeshComp(this); + pOwner->GetGame()->GetRenderer()->AddMeshComp(this); } MeshComponent::~MeshComponent() { - mOwner->GetGame()->GetRenderer()->RemoveMeshComp(this); + pOwner->GetGame()->GetRenderer()->RemoveMeshComp(this); } void MeshComponent::Draw(Shader* shader) { - if (mMesh) + if (pMesh) { // Set the world transform - shader->SetMatrixUniform("uWorldTransform", - mOwner->GetWorldTransform()); + shader->SetMatrixUniform("uWorldTransform", pOwner->GetWorldTransform()); // Set specular power - shader->SetFloatUniform("uSpecPower", mMesh->GetSpecPower()); + shader->SetFloatUniform("uSpecPower", pMesh->GetSpecPower()); // Set the active texture - Texture* t = mMesh->GetTexture(mTextureIndex); + Texture* t = pMesh->GetTexture(mTextureIndex); if (t) { t->SetActive(); } // Set the mesh's vertex array as active - VertexArray* va = mMesh->GetVertexArray(); + VertexArray* va = pMesh->GetVertexArray(); va->SetActive(); // Draw glDrawElements(GL_TRIANGLES, va->GetNumIndices(), GL_UNSIGNED_INT, nullptr); } -} +} \ No newline at end of file diff --git a/Chapter07/MeshComponent.h b/Chapter07/MeshComponent.h index 48765568..bda30a84 100644 --- a/Chapter07/MeshComponent.h +++ b/Chapter07/MeshComponent.h @@ -10,7 +10,7 @@ #include "Component.h" #include -class MeshComponent : public Component +class MeshComponent: public Component { public: MeshComponent(class Actor* owner); @@ -18,9 +18,9 @@ class MeshComponent : public Component // Draw this mesh component virtual void Draw(class Shader* shader); // Set the mesh/texture index used by mesh component - virtual void SetMesh(class Mesh* mesh) { mMesh = mesh; } + virtual void SetMesh(class Mesh* mesh) { pMesh = mesh; } void SetTextureIndex(size_t index) { mTextureIndex = index; } protected: - class Mesh* mMesh; + class Mesh* pMesh; size_t mTextureIndex; -}; +}; \ No newline at end of file diff --git a/Chapter07/MoveComponent.cpp b/Chapter07/MoveComponent.cpp index 5b51c6fc..8b96a42c 100644 --- a/Chapter07/MoveComponent.cpp +++ b/Chapter07/MoveComponent.cpp @@ -9,32 +9,27 @@ #include "MoveComponent.h" #include "Actor.h" -MoveComponent::MoveComponent(class Actor* owner, int updateOrder) -:Component(owner, updateOrder) -,mAngularSpeed(0.0f) -,mForwardSpeed(0.0f) +MoveComponent::MoveComponent(class Actor* owner, int updateOrder): Component(owner, updateOrder), mAngularSpeed(0.0f), mForwardSpeed(0.0f) { - } void MoveComponent::Update(float deltaTime) { if (!Math::NearZero(mAngularSpeed)) { - Quaternion rot = mOwner->GetRotation(); + Quaternion rot = pOwner->GetRotation(); float angle = mAngularSpeed * deltaTime; // Create quaternion for incremental rotation // (Rotate about up axis) Quaternion inc(Vector3::UnitZ, angle); // Concatenate old and new quaternion rot = Quaternion::Concatenate(rot, inc); - mOwner->SetRotation(rot); + pOwner->SetRotation(rot); } - if (!Math::NearZero(mForwardSpeed)) { - Vector3 pos = mOwner->GetPosition(); - pos += mOwner->GetForward() * mForwardSpeed * deltaTime; - mOwner->SetPosition(pos); + Vector3 pos = pOwner->GetPosition(); + pos += pOwner->GetForward() * mForwardSpeed * deltaTime; + pOwner->SetPosition(pos); } -} +} \ No newline at end of file diff --git a/Chapter07/MoveComponent.h b/Chapter07/MoveComponent.h index def7d389..c737e66b 100644 --- a/Chapter07/MoveComponent.h +++ b/Chapter07/MoveComponent.h @@ -9,13 +9,12 @@ #pragma once #include "Component.h" -class MoveComponent : public Component +class MoveComponent: public Component { public: // Lower update order to update first MoveComponent(class Actor* owner, int updateOrder = 10); void Update(float deltaTime) override; - float GetAngularSpeed() const { return mAngularSpeed; } float GetForwardSpeed() const { return mForwardSpeed; } void SetAngularSpeed(float speed) { mAngularSpeed = speed; } @@ -23,4 +22,4 @@ class MoveComponent : public Component private: float mAngularSpeed; float mForwardSpeed; -}; +}; \ No newline at end of file diff --git a/Chapter07/PlaneActor.cpp b/Chapter07/PlaneActor.cpp index 5398ca4c..696a148f 100644 --- a/Chapter07/PlaneActor.cpp +++ b/Chapter07/PlaneActor.cpp @@ -11,10 +11,9 @@ #include "Renderer.h" #include "MeshComponent.h" -PlaneActor::PlaneActor(Game* game) - :Actor(game) +PlaneActor::PlaneActor(Game* game): Actor(game) { SetScale(10.0f); MeshComponent* mc = new MeshComponent(this); mc->SetMesh(GetGame()->GetRenderer()->GetMesh("Assets/Plane.gpmesh")); -} +} \ No newline at end of file diff --git a/Chapter07/PlaneActor.h b/Chapter07/PlaneActor.h index 8187b64a..ca323e87 100644 --- a/Chapter07/PlaneActor.h +++ b/Chapter07/PlaneActor.h @@ -9,7 +9,7 @@ #pragma once #include "Actor.h" -class PlaneActor : public Actor +class PlaneActor: public Actor { public: PlaneActor(class Game* game); diff --git a/Chapter07/Renderer.cpp b/Chapter07/Renderer.cpp index ed25f3bd..69559451 100644 --- a/Chapter07/Renderer.cpp +++ b/Chapter07/Renderer.cpp @@ -16,10 +16,7 @@ #include "MeshComponent.h" #include -Renderer::Renderer(Game* game) - :mGame(game) - ,mSpriteShader(nullptr) - ,mMeshShader(nullptr) +Renderer::Renderer(Game* game): pGame(game), pSpriteShader(nullptr), pMeshShader(nullptr) { } @@ -31,8 +28,7 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) { mScreenWidth = screenWidth; mScreenHeight = screenHeight; - - // Set OpenGL attributes +// Set OpenGL attributes: // Use the core OpenGL profile SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // Specify version 3.3 @@ -48,18 +44,14 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Force OpenGL to use hardware acceleration SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); - - mWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 7)", 100, 100, - static_cast(mScreenWidth), static_cast(mScreenHeight), SDL_WINDOW_OPENGL); - if (!mWindow) + pWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 7)", 100, 100, static_cast(mScreenWidth), static_cast(mScreenHeight), SDL_WINDOW_OPENGL); + if (!pWindow) { SDL_Log("Failed to create window: %s", SDL_GetError()); return false; } - // Create an OpenGL context - mContext = SDL_GL_CreateContext(mWindow); - + mContext = SDL_GL_CreateContext(pWindow); // Initialize GLEW glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) @@ -67,33 +59,28 @@ bool Renderer::Initialize(float screenWidth, float screenHeight) SDL_Log("Failed to initialize GLEW."); return false; } - - // On some platforms, GLEW will emit a benign error code, - // so clear it + // On some platforms, GLEW will emit a benign error code, so clear it glGetError(); - // Make sure we can create/compile shaders if (!LoadShaders()) { SDL_Log("Failed to load shaders."); return false; } - // Create quad for drawing sprites CreateSpriteVerts(); - return true; } void Renderer::Shutdown() { - delete mSpriteVerts; - mSpriteShader->Unload(); - delete mSpriteShader; - mMeshShader->Unload(); - delete mMeshShader; + delete pSpriteVerts; + pSpriteShader->Unload(); + delete pSpriteShader; + pMeshShader->Unload(); + delete pMeshShader; SDL_GL_DeleteContext(mContext); - SDL_DestroyWindow(mWindow); + SDL_DestroyWindow(pWindow); } void Renderer::UnloadData() @@ -105,7 +92,6 @@ void Renderer::UnloadData() delete i.second; } mTextures.clear(); - // Destroy meshes for (auto i : mMeshes) { @@ -117,26 +103,24 @@ void Renderer::UnloadData() void Renderer::Draw() { - // Set the clear color to light grey + // Set the clear color to black glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the color buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Draw mesh components // Enable depth buffering/disable alpha blend glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); // Set the mesh shader active - mMeshShader->SetActive(); + pMeshShader->SetActive(); // Update view-projection matrix - mMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); + pMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); // Update lighting uniforms - SetLightUniforms(mMeshShader); - for (auto mc : mMeshComps) + SetLightUniforms(pMeshShader); + for (auto mc: mMeshComps) { - mc->Draw(mMeshShader); + mc->Draw(pMeshShader); } - // Draw all sprite components // Disable depth buffering glDisable(GL_DEPTH_TEST); @@ -144,35 +128,29 @@ void Renderer::Draw() glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); - - // Set shader/vao as active - mSpriteShader->SetActive(); - mSpriteVerts->SetActive(); - for (auto sprite : mSprites) + // Set shader/VAO as active + pSpriteShader->SetActive(); + pSpriteVerts->SetActive(); + for (auto sprite: mSprites) { - sprite->Draw(mSpriteShader); + sprite->Draw(pSpriteShader); } - // Swap the buffers - SDL_GL_SwapWindow(mWindow); + SDL_GL_SwapWindow(pWindow); } void Renderer::AddSprite(SpriteComponent* sprite) { - // Find the insertion point in the sorted vector - // (The first element with a higher draw order than me) + // Find the insertion point in the sorted vector (The first element with a higher draw order than me) int myDrawOrder = sprite->GetDrawOrder(); auto iter = mSprites.begin(); - for (; - iter != mSprites.end(); - ++iter) + for (; iter != mSprites.end(); ++iter) { if (myDrawOrder < (*iter)->GetDrawOrder()) { break; } } - // Inserts element before position of iterator mSprites.insert(iter, sprite); } @@ -245,30 +223,26 @@ Mesh* Renderer::GetMesh(const std::string & fileName) bool Renderer::LoadShaders() { // Create sprite shader - mSpriteShader = new Shader(); - if (!mSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag")) + pSpriteShader = new Shader(); + if (!pSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag")) { return false; } - - mSpriteShader->SetActive(); + pSpriteShader->SetActive(); // Set the view-projection matrix Matrix4 viewProj = Matrix4::CreateSimpleViewProj(mScreenWidth, mScreenHeight); - mSpriteShader->SetMatrixUniform("uViewProj", viewProj); - + pSpriteShader->SetMatrixUniform("uViewProj", viewProj); // Create basic mesh shader - mMeshShader = new Shader(); - if (!mMeshShader->Load("Shaders/Phong.vert", "Shaders/Phong.frag")) + pMeshShader = new Shader(); + if (!pMeshShader->Load("Shaders/Phong.vert", "Shaders/Phong.frag")) { return false; } - - mMeshShader->SetActive(); + pMeshShader->SetActive(); // Set the view-projection matrix mView = Matrix4::CreateLookAt(Vector3::Zero, Vector3::UnitX, Vector3::UnitZ); - mProjection = Matrix4::CreatePerspectiveFOV(Math::ToRadians(70.0f), - mScreenWidth, mScreenHeight, 25.0f, 10000.0f); - mMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); + mProjection = Matrix4::CreatePerspectiveFOV(Math::ToRadians(70.0f), mScreenWidth, mScreenHeight, 25.0f, 10000.0f); + pMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); return true; } @@ -280,13 +254,11 @@ void Renderer::CreateSpriteVerts() 0.5f,-0.5f, 0.f, 0.f, 0.f, 0.0f, 1.f, 1.f, // bottom right -0.5f,-0.5f, 0.f, 0.f, 0.f, 0.0f, 0.f, 1.f // bottom left }; - unsigned int indices[] = { 0, 1, 2, 2, 3, 0 }; - - mSpriteVerts = new VertexArray(vertices, 4, indices, 6); + pSpriteVerts = new VertexArray(vertices, 4, indices, 6); } void Renderer::SetLightUniforms(Shader* shader) @@ -298,10 +270,7 @@ void Renderer::SetLightUniforms(Shader* shader) // Ambient light shader->SetVectorUniform("uAmbientLight", mAmbientLight); // Directional light - shader->SetVectorUniform("uDirLight.mDirection", - mDirLight.mDirection); - shader->SetVectorUniform("uDirLight.mDiffuseColor", - mDirLight.mDiffuseColor); - shader->SetVectorUniform("uDirLight.mSpecColor", - mDirLight.mSpecColor); -} + shader->SetVectorUniform("uDirLight.mDirection", mDirLight.mDirection); + shader->SetVectorUniform("uDirLight.mDiffuseColor", mDirLight.mDiffuseColor); + shader->SetVectorUniform("uDirLight.mSpecColor", mDirLight.mSpecColor); +} \ No newline at end of file diff --git a/Chapter07/Renderer.h b/Chapter07/Renderer.h index 12746df2..9f04270a 100644 --- a/Chapter07/Renderer.h +++ b/Chapter07/Renderer.h @@ -28,69 +28,52 @@ class Renderer public: Renderer(class Game* game); ~Renderer(); - bool Initialize(float screenWidth, float screenHeight); void Shutdown(); void UnloadData(); - void Draw(); - void AddSprite(class SpriteComponent* sprite); void RemoveSprite(class SpriteComponent* sprite); - void AddMeshComp(class MeshComponent* mesh); void RemoveMeshComp(class MeshComponent* mesh); - class Texture* GetTexture(const std::string& fileName); class Mesh* GetMesh(const std::string& fileName); - void SetViewMatrix(const Matrix4& view) { mView = view; } - void SetAmbientLight(const Vector3& ambient) { mAmbientLight = ambient; } DirectionalLight& GetDirectionalLight() { return mDirLight; } - float GetScreenWidth() const { return mScreenWidth; } float GetScreenHeight() const { return mScreenHeight; } private: bool LoadShaders(); void CreateSpriteVerts(); void SetLightUniforms(class Shader* shader); - // Map of textures loaded std::unordered_map mTextures; // Map of meshes loaded std::unordered_map mMeshes; - // All the sprite components drawn std::vector mSprites; - // All mesh components drawn std::vector mMeshComps; - // Game - class Game* mGame; - + class Game* pGame; // Sprite shader - class Shader* mSpriteShader; + class Shader* pSpriteShader; // Sprite vertex array - class VertexArray* mSpriteVerts; - + class VertexArray* pSpriteVerts; // Mesh shader - class Shader* mMeshShader; - + class Shader* pMeshShader; // View/projection for 3D shaders Matrix4 mView; Matrix4 mProjection; // Width/height of screen float mScreenWidth; float mScreenHeight; - // Lighting data Vector3 mAmbientLight; DirectionalLight mDirLight; - // Window - SDL_Window* mWindow; + SDL_Window* pWindow; // OpenGL context SDL_GLContext mContext; }; \ No newline at end of file diff --git a/Chapter07/Shader.cpp b/Chapter07/Shader.cpp index cae3ac07..2bc5f415 100644 --- a/Chapter07/Shader.cpp +++ b/Chapter07/Shader.cpp @@ -12,45 +12,31 @@ #include #include -Shader::Shader() - : mShaderProgram(0) - , mVertexShader(0) - , mFragShader(0) +Shader::Shader(): mShaderProgram(0), mVertexShader(0), mFragShader(0) { - } Shader::~Shader() { - } bool Shader::Load(const std::string& vertName, const std::string& fragName) { // Compile vertex and pixel shaders - if (!CompileShader(vertName, - GL_VERTEX_SHADER, - mVertexShader) || - !CompileShader(fragName, - GL_FRAGMENT_SHADER, - mFragShader)) + if (!CompileShader(vertName, GL_VERTEX_SHADER, mVertexShader) || !CompileShader(fragName, GL_FRAGMENT_SHADER, mFragShader)) { return false; } - - // Now create a shader program that - // links together the vertex/frag shaders + // Now create a shader program that links together the vertex/frag shaders mShaderProgram = glCreateProgram(); glAttachShader(mShaderProgram, mVertexShader); glAttachShader(mShaderProgram, mFragShader); glLinkProgram(mShaderProgram); - // Verify that the program linked successfully if (!IsValidProgram()) { return false; } - return true; } @@ -90,9 +76,7 @@ void Shader::SetFloatUniform(const char* name, float value) glUniform1f(loc, value); } -bool Shader::CompileShader(const std::string& fileName, - GLenum shaderType, - GLuint& outShader) +bool Shader::CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader) { // Open file std::ifstream shaderFile(fileName); @@ -103,13 +87,11 @@ bool Shader::CompileShader(const std::string& fileName, sstream << shaderFile.rdbuf(); std::string contents = sstream.str(); const char* contentsChar = contents.c_str(); - // Create a shader of the specified type outShader = glCreateShader(shaderType); // Set the source characters and try to compile glShaderSource(outShader, 1, &(contentsChar), nullptr); glCompileShader(outShader); - if (!IsCompiled(outShader)) { SDL_Log("Failed to compile shader %s", fileName.c_str()); @@ -121,7 +103,6 @@ bool Shader::CompileShader(const std::string& fileName, SDL_Log("Shader file not found: %s", fileName.c_str()); return false; } - return true; } @@ -130,7 +111,6 @@ bool Shader::IsCompiled(GLuint shader) GLint status; // Query the compile status glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { char buffer[512]; @@ -139,13 +119,11 @@ bool Shader::IsCompiled(GLuint shader) SDL_Log("GLSL Compile Failed:\n%s", buffer); return false; } - return true; } bool Shader::IsValidProgram() { - GLint status; // Query the link status glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &status); @@ -157,6 +135,5 @@ bool Shader::IsValidProgram() SDL_Log("GLSL Link Status:\n%s", buffer); return false; } - return true; -} +} \ No newline at end of file diff --git a/Chapter07/Shader.h b/Chapter07/Shader.h index 929c9e41..f9c5e33e 100644 --- a/Chapter07/Shader.h +++ b/Chapter07/Shader.h @@ -29,10 +29,7 @@ class Shader void SetFloatUniform(const char* name, float value); private: // Tries to compile the specified shader - bool CompileShader(const std::string& fileName, - GLenum shaderType, - GLuint& outShader); - + bool CompileShader(const std::string& fileName, GLenum shaderType, GLuint& outShader); // Tests whether shader compiled successfully bool IsCompiled(GLuint shader); // Tests whether vertex/fragment programs link @@ -42,4 +39,4 @@ class Shader GLuint mVertexShader; GLuint mFragShader; GLuint mShaderProgram; -}; +}; \ No newline at end of file diff --git a/Chapter07/Shaders/BasicMesh.frag b/Chapter07/Shaders/BasicMesh.frag index 481a669a..54f0924f 100644 --- a/Chapter07/Shaders/BasicMesh.frag +++ b/Chapter07/Shaders/BasicMesh.frag @@ -11,10 +11,8 @@ // Tex coord input from vertex shader in vec2 fragTexCoord; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; @@ -22,4 +20,4 @@ void main() { // Sample color from texture outColor = texture(uTexture, fragTexCoord); -} +} \ No newline at end of file diff --git a/Chapter07/Shaders/BasicMesh.vert b/Chapter07/Shaders/BasicMesh.vert index 7d21ad0d..297d197b 100644 --- a/Chapter07/Shaders/BasicMesh.vert +++ b/Chapter07/Shaders/BasicMesh.vert @@ -12,12 +12,10 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is normal, 2 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoord; - // Any vertex outputs (other than position) out vec2 fragTexCoord; @@ -27,7 +25,6 @@ void main() vec4 pos = vec4(inPosition, 1.0); // Transform to position world space, then clip space gl_Position = pos * uWorldTransform * uViewProj; - // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter07/Shaders/Phong.frag b/Chapter07/Shaders/Phong.frag index 7bb2678c..081fa77e 100644 --- a/Chapter07/Shaders/Phong.frag +++ b/Chapter07/Shaders/Phong.frag @@ -16,13 +16,10 @@ in vec2 fragTexCoord; in vec3 fragNormal; // Position (in world space) in vec3 fragWorldPos; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; - // Create a struct for directional light struct DirectionalLight { @@ -33,7 +30,6 @@ struct DirectionalLight // Specular color vec3 mSpecColor; }; - // Uniforms for lighting // Camera position (in world space) uniform vec3 uCameraPos; @@ -41,7 +37,6 @@ uniform vec3 uCameraPos; uniform float uSpecPower; // Ambient light level uniform vec3 uAmbientLight; - // Directional Light uniform DirectionalLight uDirLight; @@ -55,7 +50,6 @@ void main() vec3 V = normalize(uCameraPos - fragWorldPos); // Reflection of -L about N vec3 R = normalize(reflect(-L, N)); - // Compute phong reflection vec3 Phong = uAmbientLight; float NdotL = dot(N, L); @@ -65,7 +59,6 @@ void main() vec3 Specular = uDirLight.mSpecColor * pow(max(0.0, dot(R, V)), uSpecPower); Phong += Diffuse + Specular; } - // Final color is texture color times phong light (alpha = 1) outColor = texture(uTexture, fragTexCoord) * vec4(Phong, 1.0f); -} +} \ No newline at end of file diff --git a/Chapter07/Shaders/Phong.vert b/Chapter07/Shaders/Phong.vert index af5078dc..cfa49a2b 100644 --- a/Chapter07/Shaders/Phong.vert +++ b/Chapter07/Shaders/Phong.vert @@ -12,12 +12,10 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is normal, 2 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoord; - // Any vertex outputs (other than position) out vec2 fragTexCoord; // Normal (in world space) @@ -35,10 +33,8 @@ void main() fragWorldPos = pos.xyz; // Transform to clip space gl_Position = pos * uViewProj; - // Transform normal into world space (w = 0) fragNormal = (vec4(inNormal, 0.0f) * uWorldTransform).xyz; - // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter07/Shaders/Sprite.frag b/Chapter07/Shaders/Sprite.frag index 481a669a..54f0924f 100644 --- a/Chapter07/Shaders/Sprite.frag +++ b/Chapter07/Shaders/Sprite.frag @@ -11,10 +11,8 @@ // Tex coord input from vertex shader in vec2 fragTexCoord; - // This corresponds to the output color to the color buffer out vec4 outColor; - // This is used for the texture sampling uniform sampler2D uTexture; @@ -22,4 +20,4 @@ void main() { // Sample color from texture outColor = texture(uTexture, fragTexCoord); -} +} \ No newline at end of file diff --git a/Chapter07/Shaders/Sprite.vert b/Chapter07/Shaders/Sprite.vert index 7d21ad0d..297d197b 100644 --- a/Chapter07/Shaders/Sprite.vert +++ b/Chapter07/Shaders/Sprite.vert @@ -12,12 +12,10 @@ // Uniforms for world transform and view-proj uniform mat4 uWorldTransform; uniform mat4 uViewProj; - // Attribute 0 is position, 1 is normal, 2 is tex coords. layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoord; - // Any vertex outputs (other than position) out vec2 fragTexCoord; @@ -27,7 +25,6 @@ void main() vec4 pos = vec4(inPosition, 1.0); // Transform to position world space, then clip space gl_Position = pos * uWorldTransform * uViewProj; - // Pass along the texture coordinate to frag shader fragTexCoord = inTexCoord; -} +} \ No newline at end of file diff --git a/Chapter07/SoundEvent.cpp b/Chapter07/SoundEvent.cpp index 6edbda39..2feaa07c 100644 --- a/Chapter07/SoundEvent.cpp +++ b/Chapter07/SoundEvent.cpp @@ -10,26 +10,22 @@ #include "AudioSystem.h" #include -SoundEvent::SoundEvent(class AudioSystem* system, unsigned int id) - :mSystem(system) - ,mID(id) +SoundEvent::SoundEvent(class AudioSystem* system, unsigned int id): pSystem(system), mID(id) { } -SoundEvent::SoundEvent() - :mSystem(nullptr) - ,mID(0) +SoundEvent::SoundEvent(): pSystem(nullptr), mID(0) { } bool SoundEvent::IsValid() { - return (mSystem && mSystem->GetEventInstance(mID) != nullptr); + return (pSystem && pSystem->GetEventInstance(mID) != nullptr); } void SoundEvent::Restart() { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->start(); @@ -38,19 +34,17 @@ void SoundEvent::Restart() void SoundEvent::Stop(bool allowFadeOut /* true */) { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { - FMOD_STUDIO_STOP_MODE mode = allowFadeOut ? - FMOD_STUDIO_STOP_ALLOWFADEOUT : - FMOD_STUDIO_STOP_IMMEDIATE; + FMOD_STUDIO_STOP_MODE mode = allowFadeOut ? FMOD_STUDIO_STOP_ALLOWFADEOUT : FMOD_STUDIO_STOP_IMMEDIATE; event->stop(mode); } } void SoundEvent::SetPaused(bool pause) { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->setPaused(pause); @@ -59,7 +53,7 @@ void SoundEvent::SetPaused(bool pause) void SoundEvent::SetVolume(float value) { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->setVolume(value); @@ -68,7 +62,7 @@ void SoundEvent::SetVolume(float value) void SoundEvent::SetPitch(float value) { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->setPitch(value); @@ -77,17 +71,17 @@ void SoundEvent::SetPitch(float value) void SoundEvent::SetParameter(const std::string& name, float value) { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { - event->setParameterValue(name.c_str(), value); + event->setParameterByName(name.c_str(), value); } } bool SoundEvent::GetPaused() const { bool retVal = false; - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->getPaused(&retVal); @@ -98,7 +92,7 @@ bool SoundEvent::GetPaused() const float SoundEvent::GetVolume() const { float retVal = 0.0f; - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->getVolume(&retVal); @@ -109,7 +103,7 @@ float SoundEvent::GetVolume() const float SoundEvent::GetPitch() const { float retVal = 0.0f; - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { event->getPitch(&retVal); @@ -120,10 +114,10 @@ float SoundEvent::GetPitch() const float SoundEvent::GetParameter(const std::string& name) { float retVal = 0.0f; - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { - event->getParameterValue(name.c_str(), &retVal); + event->getParameterByName(name.c_str(), &retVal); } return retVal; } @@ -131,7 +125,7 @@ float SoundEvent::GetParameter(const std::string& name) bool SoundEvent::Is3D() const { bool retVal = false; - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { // Get the event description @@ -159,9 +153,9 @@ namespace } } -void SoundEvent::Set3DAttributes(const Matrix4& worldTrans) +void SoundEvent::Set3DAttributes(const Matrix4& worldTrans, const Vector3& velocity) { - auto event = mSystem ? mSystem->GetEventInstance(mID) : nullptr; + auto event = pSystem ? pSystem->GetEventInstance(mID) : nullptr; if (event) { FMOD_3D_ATTRIBUTES attr; @@ -171,8 +165,8 @@ void SoundEvent::Set3DAttributes(const Matrix4& worldTrans) attr.forward = VecToFMOD(worldTrans.GetXAxis()); // Third row is up attr.up = VecToFMOD(worldTrans.GetZAxis()); - // Set velocity to zero (fix if using Doppler effect) - attr.velocity = { 0.0f, 0.0f, 0.0f }; + // Set velocity + attr.velocity = VecToFMOD(velocity); event->set3DAttributes(&attr); } -} +} \ No newline at end of file diff --git a/Chapter07/SoundEvent.h b/Chapter07/SoundEvent.h index ae78ac8a..7391c738 100644 --- a/Chapter07/SoundEvent.h +++ b/Chapter07/SoundEvent.h @@ -32,13 +32,13 @@ class SoundEvent float GetParameter(const std::string& name); // Positional bool Is3D() const; - void Set3DAttributes(const Matrix4& worldTrans); + void Set3DAttributes(const Matrix4& worldTrans, const Vector3& velocity = Vector3::Zero); protected: // Make this constructor protected and AudioSystem a friend // so that only AudioSystem can access this constructor. friend class AudioSystem; SoundEvent(class AudioSystem* system, unsigned int id); private: - class AudioSystem* mSystem; + class AudioSystem* pSystem; unsigned int mID; }; \ No newline at end of file diff --git a/Chapter07/SpriteComponent.cpp b/Chapter07/SpriteComponent.cpp index eb7b77aa..1708f4d6 100644 --- a/Chapter07/SpriteComponent.cpp +++ b/Chapter07/SpriteComponent.cpp @@ -13,40 +13,28 @@ #include "Game.h" #include "Renderer.h" -SpriteComponent::SpriteComponent(Actor* owner, int drawOrder) - :Component(owner) - ,mTexture(nullptr) - ,mDrawOrder(drawOrder) - ,mTexWidth(0) - ,mTexHeight(0) +SpriteComponent::SpriteComponent(Actor* owner, int drawOrder): Component(owner), pTexture(nullptr), mDrawOrder(drawOrder), mTexWidth(0), mTexHeight(0) { - mOwner->GetGame()->GetRenderer()->AddSprite(this); + pOwner->GetGame()->GetRenderer()->AddSprite(this); } SpriteComponent::~SpriteComponent() { - mOwner->GetGame()->GetRenderer()->RemoveSprite(this); + pOwner->GetGame()->GetRenderer()->RemoveSprite(this); } void SpriteComponent::Draw(Shader* shader) { - if (mTexture) + if (pTexture) { // Scale the quad by the width/height of texture - Matrix4 scaleMat = Matrix4::CreateScale( - static_cast(mTexWidth), - static_cast(mTexHeight), - 1.0f); - - Matrix4 world = scaleMat * mOwner->GetWorldTransform(); - - // Since all sprites use the same shader/vertices, - // the game first sets them active before any sprite draws - + Matrix4 scaleMat = Matrix4::CreateScale( static_cast(mTexWidth), static_cast(mTexHeight), 1.0f); + Matrix4 world = scaleMat * pOwner->GetWorldTransform(); + // Since all sprites use the same shader/vertices, the game first sets them active before any sprite draws // Set world transform shader->SetMatrixUniform("uWorldTransform", world); // Set current texture - mTexture->SetActive(); + pTexture->SetActive(); // Draw quad glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); } @@ -54,8 +42,8 @@ void SpriteComponent::Draw(Shader* shader) void SpriteComponent::SetTexture(Texture* texture) { - mTexture = texture; + pTexture = texture; // Set width/height mTexWidth = texture->GetWidth(); mTexHeight = texture->GetHeight(); -} +} \ No newline at end of file diff --git a/Chapter07/SpriteComponent.h b/Chapter07/SpriteComponent.h index 6c5642f2..581cb883 100644 --- a/Chapter07/SpriteComponent.h +++ b/Chapter07/SpriteComponent.h @@ -9,22 +9,20 @@ #pragma once #include "Component.h" #include "SDL/SDL.h" -class SpriteComponent : public Component +class SpriteComponent: public Component { public: // (Lower draw order corresponds with further back) SpriteComponent(class Actor* owner, int drawOrder = 100); ~SpriteComponent(); - virtual void Draw(class Shader* shader); virtual void SetTexture(class Texture* texture); - int GetDrawOrder() const { return mDrawOrder; } int GetTexHeight() const { return mTexHeight; } int GetTexWidth() const { return mTexWidth; } protected: - class Texture* mTexture; + class Texture* pTexture; int mDrawOrder; int mTexWidth; int mTexHeight; -}; +}; \ No newline at end of file diff --git a/Chapter07/Texture.cpp b/Chapter07/Texture.cpp index ddde35f0..a2c632c9 100644 --- a/Chapter07/Texture.cpp +++ b/Chapter07/Texture.cpp @@ -11,50 +11,35 @@ #include #include -Texture::Texture() -:mTextureID(0) -,mWidth(0) -,mHeight(0) +Texture::Texture(): mTextureID(0), mWidth(0), mHeight(0) { - } Texture::~Texture() { - } bool Texture::Load(const std::string& fileName) { int channels = 0; - - unsigned char* image = SOIL_load_image(fileName.c_str(), - &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); - + unsigned char* image = SOIL_load_image(fileName.c_str(), &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); if (image == nullptr) { SDL_Log("SOIL failed to load image %s: %s", fileName.c_str(), SOIL_last_result()); return false; } - int format = GL_RGB; if (channels == 4) { format = GL_RGBA; } - glGenTextures(1, &mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID); - - glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, - GL_UNSIGNED_BYTE, image); - + glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, GL_UNSIGNED_BYTE, image); SOIL_free_image_data(image); - // Enable linear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - return true; } @@ -66,4 +51,4 @@ void Texture::Unload() void Texture::SetActive() { glBindTexture(GL_TEXTURE_2D, mTextureID); -} +} \ No newline at end of file diff --git a/Chapter07/Texture.h b/Chapter07/Texture.h index 6c8892fd..b2059450 100644 --- a/Chapter07/Texture.h +++ b/Chapter07/Texture.h @@ -13,16 +13,13 @@ class Texture public: Texture(); ~Texture(); - bool Load(const std::string& fileName); void Unload(); - void SetActive(); - int GetWidth() const { return mWidth; } int GetHeight() const { return mHeight; } private: unsigned int mTextureID; int mWidth; int mHeight; -}; +}; \ No newline at end of file diff --git a/Chapter07/VertexArray.cpp b/Chapter07/VertexArray.cpp index faddcf6c..e97c3bdd 100644 --- a/Chapter07/VertexArray.cpp +++ b/Chapter07/VertexArray.cpp @@ -9,25 +9,19 @@ #include "VertexArray.h" #include -VertexArray::VertexArray(const float* verts, unsigned int numVerts, - const unsigned int* indices, unsigned int numIndices) - :mNumVerts(numVerts) - ,mNumIndices(numIndices) +VertexArray::VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices): mNumVerts(numVerts), mNumIndices(numIndices) { // Create vertex array glGenVertexArrays(1, &mVertexArray); glBindVertexArray(mVertexArray); - // Create vertex buffer glGenBuffers(1, &mVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); glBufferData(GL_ARRAY_BUFFER, numVerts * 8 * sizeof(float), verts, GL_STATIC_DRAW); - // Create index buffer glGenBuffers(1, &mIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned int), indices, GL_STATIC_DRAW); - // Specify the vertex attributes // (For now, assume one vertex format) // Position is 3 floats @@ -35,12 +29,10 @@ VertexArray::VertexArray(const float* verts, unsigned int numVerts, glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0); // Normal is 3 floats glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), - reinterpret_cast(sizeof(float) * 3)); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast(sizeof(float) * 3)); // Texture coordinates is 2 floats glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), - reinterpret_cast(sizeof(float) * 6)); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), reinterpret_cast(sizeof(float) * 6)); } VertexArray::~VertexArray() @@ -53,4 +45,4 @@ VertexArray::~VertexArray() void VertexArray::SetActive() { glBindVertexArray(mVertexArray); -} +} \ No newline at end of file diff --git a/Chapter07/VertexArray.h b/Chapter07/VertexArray.h index 5deddc4d..480a254b 100644 --- a/Chapter07/VertexArray.h +++ b/Chapter07/VertexArray.h @@ -10,10 +10,8 @@ class VertexArray { public: - VertexArray(const float* verts, unsigned int numVerts, - const unsigned int* indices, unsigned int numIndices); + VertexArray(const float* verts, unsigned int numVerts, const unsigned int* indices, unsigned int numIndices); ~VertexArray(); - void SetActive(); unsigned int GetNumIndices() const { return mNumIndices; } unsigned int GetNumVerts() const { return mNumVerts; } diff --git a/TODO.txt b/TODO.txt index 1dd235e5..635d3a14 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,4 @@ TODO: -6.1 - Multiple mesh shaders -6.2 - Point lights -7.1 - Add velocity to the listener 7.2 - Virtual positions for events 8.1 - Controller support 8.2 - Abstract input mapping @@ -32,4 +29,7 @@ Skipped: Done: 4.1 - State Machine 5.1 - Updating exercise -5.2 - Add vertex color (RGB) to sprite shader \ No newline at end of file +5.2 - Add vertex color (RGB) to sprite shader +6.1 - Multiple mesh shaders +6.2 - Point lights +7.1 - Add velocity to the listener \ No newline at end of file