Sanjay Madhav 8 лет назад
Родитель
Сommit
75f5b512eb

+ 54 - 9
Chapter06/Actor.cpp

@@ -14,9 +14,10 @@
 Actor::Actor(Game* game)
 	:mState(EActive)
 	,mPosition(Vector3::Zero)
-	, mRotation(Quaternion::Identity)
+	,mRotation(Quaternion::Identity)
 	,mScale(1.0f)
 	,mGame(game)
+	,mRecomputeWorldTransform(true)
 {
 	mGame->AddActor(this);
 }
@@ -36,8 +37,12 @@ void Actor::Update(float deltaTime)
 {
 	if (mState == EActive)
 	{
+		ComputeWorldTransform();
+
 		UpdateComponents(deltaTime);
 		UpdateActor(deltaTime);
+
+		ComputeWorldTransform();
 	}
 }
 
@@ -53,20 +58,60 @@ void Actor::UpdateActor(float deltaTime)
 {
 }
 
+void Actor::ProcessInput(const uint8_t* keyState)
+{
+	if (mState == EActive)
+	{
+		// First process input for components
+		for (auto comp : mComponents)
+		{
+			comp->ProcessInput(keyState);
+		}
+
+		ActorInput(keyState);
+	}
+}
+
+void Actor::ActorInput(const uint8_t* keyState)
+{
+}
+
 void Actor::ComputeWorldTransform()
 {
-	// Scale, then rotate, then translate
-	mWorldTransform = Matrix4::CreateScale(mScale);
-	mWorldTransform *= Matrix4::CreateFromQuaternion(mRotation);
-	mWorldTransform *= Matrix4::CreateTranslation(mPosition);
+	if (mRecomputeWorldTransform)
+	{
+		mRecomputeWorldTransform = false;
+		// Scale, then rotate, then translate
+		mWorldTransform = Matrix4::CreateScale(mScale);
+		mWorldTransform *= Matrix4::CreateFromQuaternion(mRotation);
+		mWorldTransform *= Matrix4::CreateTranslation(mPosition);
+
+		// Inform components world transform updated
+		for (auto comp : mComponents)
+		{
+			comp->OnUpdateWorldTransform();
+		}
+	}
 }
 
 void Actor::AddComponent(Component* component)
 {
-	mComponents.emplace_back(component);
-	std::sort(mComponents.begin(), mComponents.end(), [](Component* a, Component* b) {
-		return a->GetUpdateOrder() < b->GetUpdateOrder();
-	});
+	// 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)
+	{
+		if (myOrder < (*iter)->GetUpdateOrder())
+		{
+			break;
+		}
+	}
+
+	// Inserts element before position of iterator
+	mComponents.insert(iter, component);
 }
 
 void Actor::RemoveComponent(Component* component)

+ 10 - 4
Chapter06/Actor.h

@@ -9,6 +9,8 @@
 #pragma once
 #include <vector>
 #include "Math.h"
+#include <cstdint>
+
 class Actor
 {
 public:
@@ -28,16 +30,19 @@ public:
 	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 ProcessInput(const uint8_t* keys) { }
+	virtual void ActorInput(const uint8_t* keyState);
 
 	// Getters/setters
 	const Vector3& GetPosition() const { return mPosition; }
-	void SetPosition(const Vector3& pos) { mPosition = pos; ComputeWorldTransform(); }
+	void SetPosition(const Vector3& pos) { mPosition = pos; mRecomputeWorldTransform = true; }
 	float GetScale() const { return mScale; }
-	void SetScale(float scale) { mScale = scale;  ComputeWorldTransform(); }
+	void SetScale(float scale) { mScale = scale;  mRecomputeWorldTransform = true; }
 	const Quaternion& GetRotation() const { return mRotation; }
-	void SetRotation(const Quaternion& rotation) { mRotation = rotation;  ComputeWorldTransform(); }
+	void SetRotation(const Quaternion& rotation) { mRotation = rotation;  mRecomputeWorldTransform = true; }
 	
 	void ComputeWorldTransform();
 	const Matrix4& GetWorldTransform() const { return mWorldTransform; }
@@ -62,6 +67,7 @@ private:
 	Vector3 mPosition;
 	Quaternion mRotation;
 	float mScale;
+	bool mRecomputeWorldTransform;
 
 	std::vector<class Component*> mComponents;
 	class Game* mGame;

+ 1 - 1
Chapter06/CameraActor.cpp

@@ -31,7 +31,7 @@ void CameraActor::UpdateActor(float deltaTime)
 	GetGame()->GetRenderer()->SetViewMatrix(view);
 }
 
-void CameraActor::ProcessInput(const uint8_t* keys)
+void CameraActor::ActorInput(const uint8_t* keys)
 {
 	float forwardSpeed = 0.0f;
 	float angularSpeed = 0.0f;

+ 2 - 2
Chapter06/CameraActor.h

@@ -15,7 +15,7 @@ public:
 	CameraActor(class Game* game);
 
 	void UpdateActor(float deltaTime) override;
-	void ProcessInput(const uint8_t* keys) override;
+	void ActorInput(const uint8_t* keys) override;
 private:
 	class MoveComponent* mMoveComp;
-};
+};

+ 6 - 0
Chapter06/Component.h

@@ -7,6 +7,8 @@
 // ----------------------------------------------------------------
 
 #pragma once
+#include <cstdint>
+
 class Component
 {
 public:
@@ -17,6 +19,10 @@ public:
 	virtual ~Component();
 	// Update this component by delta time
 	virtual void Update(float deltaTime);
+	// Process input for this component
+	virtual void ProcessInput(const uint8_t* keyState) {}
+	// Called when world transform changes
+	virtual void OnUpdateWorldTransform() { }
 
 	int GetUpdateOrder() const { return mUpdateOrder; }
 protected:

+ 33 - 9
Chapter06/Game.cpp

@@ -18,6 +18,7 @@
 Game::Game()
 :mRenderer(nullptr)
 ,mIsRunning(true)
+,mUpdatingActors(false)
 {
 	
 }
@@ -96,15 +97,21 @@ void Game::UpdateGame()
 	}
 	mTicksCount = SDL_GetTicks();
 
-	// Make copy of actor vector
-	// (iterate over this in case new actors are created)
-	std::vector<Actor*> copy = mActors;
-
 	// Update all actors
-	for (auto actor : copy)
+	mUpdatingActors = true;
+	for (auto actor : mActors)
 	{
 		actor->Update(deltaTime);
 	}
+	mUpdatingActors = false;
+
+	// Move any pending actors to mActors
+	for (auto pending : mPendingActors)
+	{
+		pending->ComputeWorldTransform();
+		mActors.emplace_back(pending);
+	}
+	mPendingActors.clear();
 
 	// Add any dead actors to a temp vector
 	std::vector<Actor*> deadActors;
@@ -116,8 +123,7 @@ void Game::UpdateGame()
 		}
 	}
 
-	// Delete any of the dead actors (which will
-	// remove them from mActors)
+	// Delete dead actors (which removes them from mActors)
 	for (auto actor : deadActors)
 	{
 		delete actor;
@@ -235,12 +241,30 @@ void Game::Shutdown()
 
 void Game::AddActor(Actor* actor)
 {
-	mActors.emplace_back(actor);
+	// If we're updating actors, need to add to pending
+	if (mUpdatingActors)
+	{
+		mPendingActors.emplace_back(actor);
+	}
+	else
+	{
+		mActors.emplace_back(actor);
+	}
 }
 
 void Game::RemoveActor(Actor* actor)
 {
-	auto iter = std::find(mActors.begin(), mActors.end(), actor);
+	// Is it in pending actors?
+	auto iter = std::find(mPendingActors.begin(), mPendingActors.end(), actor);
+	if (iter != mPendingActors.end())
+	{
+		// Swap to end of vector and pop off (avoid erase copies)
+		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())
 	{
 		// Swap to end of vector and pop off (avoid erase copies)

+ 4 - 0
Chapter06/Game.h

@@ -34,11 +34,15 @@ private:
 	
 	// All the actors in the game
 	std::vector<class Actor*> mActors;
+	// Any pending actors
+	std::vector<class Actor*> mPendingActors;
 
 	class Renderer* mRenderer;
 
 	Uint32 mTicksCount;
 	bool mIsRunning;
+	// Track if we're updating actors right now
+	bool mUpdatingActors;
 
 	// Game-specific code
 	class CameraActor* mCameraActor;

+ 18 - 7
Chapter06/Renderer.cpp

@@ -159,11 +159,22 @@ void Renderer::Draw()
 
 void Renderer::AddSprite(SpriteComponent* sprite)
 {
-	mSprites.emplace_back(sprite);
-	// Resort sprites by draw order
-	std::sort(mSprites.begin(), mSprites.end(), [](SpriteComponent* a, SpriteComponent* b) {
-		return a->GetDrawOrder() < b->GetDrawOrder();
-	});
+	// 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)
+	{
+		if (myDrawOrder < (*iter)->GetDrawOrder())
+		{
+			break;
+		}
+	}
+
+	// Inserts element before position of iterator
+	mSprites.insert(iter, sprite);
 }
 
 void Renderer::RemoveSprite(SpriteComponent* sprite)
@@ -235,7 +246,7 @@ bool Renderer::LoadShaders()
 {
 	// Create sprite shader
 	mSpriteShader = new Shader();
-	if (!mSpriteShader->Load("Shaders/Sprite"))
+	if (!mSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag"))
 	{
 		return false;
 	}
@@ -247,7 +258,7 @@ bool Renderer::LoadShaders()
 
 	// Create basic mesh shader
 	mMeshShader = new Shader();
-	if (!mMeshShader->Load("Shaders/Phong"))
+	if (!mMeshShader->Load("Shaders/Phong.vert", "Shaders/Phong.frag"))
 	{
 		return false;
 	}

+ 10 - 10
Chapter06/Shader.cpp

@@ -25,15 +25,15 @@ Shader::~Shader()
 
 }
 
-bool Shader::Load(const std::string& name)
+bool Shader::Load(const std::string& vertName, const std::string& fragName)
 {
 	// Compile vertex and pixel shaders
-	if (!CompileShader(name + ".vert",
-					   GL_VERTEX_SHADER,
-					   mVertexShader) ||
-		!CompileShader(name + ".frag",
-					   GL_FRAGMENT_SHADER,
-					   mFragShader))
+	if (!CompileShader(vertName,
+		GL_VERTEX_SHADER,
+		mVertexShader) ||
+		!CompileShader(fragName,
+			GL_FRAGMENT_SHADER,
+			mFragShader))
 	{
 		return false;
 	}
@@ -91,14 +91,14 @@ void Shader::SetFloatUniform(const char* name, float value)
 }
 
 bool Shader::CompileShader(const std::string& fileName,
-				   GLenum shaderType,
-				   GLuint& outShader)
+	GLenum shaderType,
+	GLuint& outShader)
 {
 	// Open file
 	std::ifstream shaderFile(fileName);
 	if (shaderFile.is_open())
 	{
-		// Read all of the text into a string
+		// Read all the text into a string
 		std::stringstream sstream;
 		sstream << shaderFile.rdbuf();
 		std::string contents = sstream.str();

+ 2 - 3
Chapter06/Shader.h

@@ -16,9 +16,8 @@ class Shader
 public:
 	Shader();
 	~Shader();
-	// Load shader of the specified name, excluding
-	// the .frag/.vert extension
-	bool Load(const std::string& name);
+	// Load the vertex/fragment shaders with the given names
+	bool Load(const std::string& vertName, const std::string& fragName);
 	void Unload();
 	// Set this as the active shader program
 	void SetActive();

+ 1 - 2
Chapter06/VertexArray.cpp

@@ -26,7 +26,7 @@ VertexArray::VertexArray(const float* verts, unsigned int numVerts,
 	// Create index buffer
 	glGenBuffers(1, &mIndexBuffer);
 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
-	glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(GLuint), indices, GL_STATIC_DRAW);
+	glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned int), indices, GL_STATIC_DRAW);
 
 	// Specify the vertex attributes
 	// (For now, assume one vertex format)
@@ -53,5 +53,4 @@ VertexArray::~VertexArray()
 void VertexArray::SetActive()
 {
 	glBindVertexArray(mVertexArray);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
 }

+ 5 - 0
Chapter06/VertexArray.h

@@ -18,9 +18,14 @@ public:
 	unsigned int GetNumIndices() const { return mNumIndices; }
 	unsigned int GetNumVerts() const { return mNumVerts; }
 private:
+	// How many vertices in the vertex buffer?
 	unsigned int mNumVerts;
+	// How many indices in the index buffer
 	unsigned int mNumIndices;
+	// OpenGL ID of the vertex buffer
 	unsigned int mVertexBuffer;
+	// OpenGL ID of the index buffer
 	unsigned int mIndexBuffer;
+	// OpenGL ID of the vertex array object
 	unsigned int mVertexArray;
 };