Merge branch 'master' of https://github.com/teamfisk/TacticalZ into Importer
# Conflicts: # include/Engine/Collision/Collision.h # src/Engine/Rendering/Model.cpp # src/Engine/Rendering/RawModelAssimp.cpp
This commit is contained in:
@@ -7,10 +7,10 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Core/Ray.h"
|
||||
#include "Core/AABB.h"
|
||||
#include "../Core/Ray.h"
|
||||
#include "../Core/AABB.h"
|
||||
#include "Engine/Rendering/RawModelAssimp.h"
|
||||
#include "Core/Entity.h"
|
||||
#include "../Core/Entity.h"
|
||||
|
||||
class World;
|
||||
struct ComponentWrapper;
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/common.hpp>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/EKeyUp.h"
|
||||
#include "../Common.h"
|
||||
#include "../Core/System.h"
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "../Core/EKeyUp.h"
|
||||
|
||||
class CollisionSystem : public PureSystem
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <glm/common.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "Core/System.h"
|
||||
#include "Core/EventBroker.h"
|
||||
#include "../Core/System.h"
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "ETrigger.h"
|
||||
|
||||
class AABB;
|
||||
|
||||
@@ -14,6 +14,7 @@ struct ComponentInfo
|
||||
|
||||
struct Field_t
|
||||
{
|
||||
std::string Name;
|
||||
std::string Type;
|
||||
unsigned int Offset;
|
||||
unsigned int Stride;
|
||||
@@ -21,7 +22,7 @@ struct ComponentInfo
|
||||
|
||||
std::string Name;
|
||||
std::unordered_map<std::string, Field_t> Fields;
|
||||
std::vector<const Field_t*> FieldsInOrder;
|
||||
std::vector<std::string> FieldsInOrder;
|
||||
Meta_t Meta;
|
||||
std::shared_ptr<char> Defaults = nullptr;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define Ray_h__
|
||||
|
||||
#include "../GLM.h"
|
||||
#include "Common.h"
|
||||
#include "../Common.h"
|
||||
|
||||
class Ray
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
/** Base Resource class.
|
||||
|
||||
Implement this class for every resource to be handled by the resource manager.
|
||||
Implement Create() to return a new object of that type.
|
||||
*/
|
||||
class Resource
|
||||
{
|
||||
@@ -22,6 +21,23 @@ protected:
|
||||
Resource() { }
|
||||
|
||||
public:
|
||||
//Should be thrown in a Resource's constructor if it cannot complete because another resource is still loading.
|
||||
//Not actually an error, just a message to the ResourceManager.
|
||||
struct StillLoadingException : public std::exception
|
||||
{
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "Resource is still loading.";
|
||||
}
|
||||
};
|
||||
struct FailedLoadingException : public std::exception
|
||||
{
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "Resource is failed to load.";
|
||||
}
|
||||
};
|
||||
|
||||
// Pretend that this is a pure virtual function that you have to implement
|
||||
// FIXME: Why did we do this again instead of just using the constructor?
|
||||
// static Resource* Create(std::string resourceName);
|
||||
@@ -33,6 +49,15 @@ public:
|
||||
unsigned int ResourceID;
|
||||
};
|
||||
|
||||
//Any class inheriting from this class will always be loaded on the master thread, not on a parallel worker thread.
|
||||
//This is important in case some instructions must be executed on the main thread, e.g. OpenGL commands, like glBindBuffer.
|
||||
//This resource can still be loaded asyncronously, but it will not be loaded in a thread, instead it's constructor will
|
||||
//be called once on every ResourceManager::Load, just throw StillLoadingException in the constructor if it is not done yet.
|
||||
class ThreadUnsafeResource : public Resource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
};
|
||||
|
||||
/** Singleton resource manager to keep track of and cache any external engine assets */
|
||||
class ResourceManager
|
||||
{
|
||||
@@ -40,6 +65,7 @@ private:
|
||||
ResourceManager();
|
||||
|
||||
public:
|
||||
static bool UseThreading;
|
||||
/*static ResourceManager& Instance()
|
||||
{
|
||||
static ResourceManager s;
|
||||
@@ -49,15 +75,6 @@ public:
|
||||
template <typename T>
|
||||
static void RegisterType(std::string typeName);
|
||||
|
||||
/** Preloads a resource and caches it for future use
|
||||
|
||||
@tparam T Resource type.
|
||||
@param resourceName Fully qualified name of the resource to preload.
|
||||
*/
|
||||
template <typename T>
|
||||
static void Preload(std::string resourceName);
|
||||
static void Preload(std::string resourceType, std::string resourceName);
|
||||
|
||||
/** Checks if a resource is in cache
|
||||
|
||||
@param resourceType Resource type as string.
|
||||
@@ -65,15 +82,20 @@ public:
|
||||
*/
|
||||
// TODO: Templateify
|
||||
static bool IsResourceLoaded(std::string resourceType, std::string resourceName);
|
||||
|
||||
/** Return value should always be a valid pointer, will throw an exception on error.
|
||||
If the resource has been loaded already, returns a pointer to it.
|
||||
|
||||
/** Hot-loads a resource and caches it for future use
|
||||
If Async is false: Hot-loads a resource, caches it for future use, and returns a pointer to it.
|
||||
If Async is true: If the resource is not loaded yet, starts loading the resource
|
||||
in the background and throws Resource::StillLoadingException immediately.
|
||||
|
||||
@tparam T Resource type.
|
||||
@tparam async Set this to true if the resource should be loaded asyncronously.
|
||||
@param resourceName Fully qualified name of the resource to load.
|
||||
*/
|
||||
template <typename T>
|
||||
static T* Load(std::string resourceName, Resource* parent = nullptr);
|
||||
static Resource* Load(std::string resourceType, std::string resourceName, Resource* parent = nullptr);
|
||||
template <typename T, bool async = false>
|
||||
static T* Load(const std::string& resourceName, Resource* parent = nullptr);
|
||||
|
||||
/** Reloads an already loaded resource, keeping its resource ID intact.
|
||||
|
||||
@@ -87,19 +109,31 @@ public:
|
||||
static void Update();
|
||||
|
||||
private:
|
||||
//This is a haxy way to make sure that IsMainThread is run when the program starts, so the master thread id is set.
|
||||
struct MasterThreadChecker
|
||||
{
|
||||
MasterThreadChecker()
|
||||
{
|
||||
ResourceManager::IsMainThread();
|
||||
}
|
||||
};
|
||||
const static MasterThreadChecker m_Checker;
|
||||
|
||||
static std::unordered_map<std::string, std::string> m_CompilerTypenameToResourceType;
|
||||
static std::unordered_map<std::string, std::function<Resource*(std::string)>> m_FactoryFunctions; // type -> factory function
|
||||
static std::unordered_map<std::pair<std::string, std::string>, Resource*> m_ResourceCache; // (type, name) -> resource
|
||||
static std::unordered_map<std::string, Resource*> m_ResourceFromName; // name -> resource
|
||||
static std::unordered_map<Resource*, Resource*> m_ResourceParents; // resource -> parent resource
|
||||
|
||||
static std::unordered_map<std::pair<std::string, std::string>, boost::thread> m_LoadingThreads; // (type, name) -> loading thread
|
||||
static std::unordered_map<std::pair<std::string, std::string>, std::exception_ptr> m_LoadingThreadExceptions; // (type, name) -> exceptions
|
||||
static boost::recursive_mutex m_Mutex;
|
||||
|
||||
// TODO: Getters for IDs
|
||||
static unsigned int m_CurrentResourceTypeID;
|
||||
static std::unordered_map<std::string, unsigned int> m_ResourceTypeIDs;
|
||||
// Number of resources of a type. Doubles as local ID.
|
||||
static std::unordered_map<unsigned int, unsigned int> m_ResourceCount;
|
||||
// Flag to suppress hot-load warnings when a preloading resource chain loads another resource
|
||||
static bool m_Preloading;
|
||||
|
||||
static FileWatcher m_FileWatcher;
|
||||
static void fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags);
|
||||
@@ -108,22 +142,13 @@ private:
|
||||
static unsigned int GetNewResourceID(unsigned int typeID);
|
||||
|
||||
// Internal: Create a resource and cache it
|
||||
static Resource* CreateResource(std::string resourceType, std::string resourceName, Resource* parent);
|
||||
static Resource* createResourceThrowing(const std::string& resourceType, const std::string& resourceName, Resource* parent);
|
||||
static Resource* createResource(const std::string& resourceType, const std::string& resourceName, Resource* parent, std::exception_ptr& exception);
|
||||
static Resource* cacheResource(Resource* resource, const std::string& resourceType, const std::string& resourceName, Resource* parent);
|
||||
|
||||
static bool IsMainThread();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T* ResourceManager::Load(std::string resourceName, Resource* parent /* = nullptr */)
|
||||
{
|
||||
auto resourceTypename = typeid(T).name();
|
||||
auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
|
||||
if (it == m_CompilerTypenameToResourceType.end()) {
|
||||
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<T*>(Load(it->second, resourceName, parent));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ResourceManager::RegisterType(std::string typeName)
|
||||
{
|
||||
@@ -131,17 +156,85 @@ void ResourceManager::RegisterType(std::string typeName)
|
||||
m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ResourceManager::Preload(std::string resourceName)
|
||||
template <typename T, bool async>
|
||||
static T* ResourceManager::Load(const std::string& resourceName, Resource* parent /* = nullptr */)
|
||||
{
|
||||
auto resourceTypename = typeid(T).name();
|
||||
auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
|
||||
if (it == m_CompilerTypenameToResourceType.end()) {
|
||||
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
|
||||
return;
|
||||
}
|
||||
auto resourceTypename = typeid(T).name();
|
||||
auto iter = m_CompilerTypenameToResourceType.find(resourceTypename);
|
||||
if (iter == m_CompilerTypenameToResourceType.end()) {
|
||||
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
|
||||
throw Resource::FailedLoadingException();
|
||||
}
|
||||
|
||||
Preload(it->second, resourceName);
|
||||
std::string resourceType = iter->second;
|
||||
constexpr bool mustNotLoadInThread = std::is_base_of<ThreadUnsafeResource, T>::value;
|
||||
if (mustNotLoadInThread && !IsMainThread()) {
|
||||
LOG_ERROR("Failed to Load \"%s\": ThreadUnsafeResource type \"%s\" load in the constructor of another resource that is loaded asyncronously.", resourceName.c_str(), iter->second.c_str());
|
||||
throw Resource::FailedLoadingException();
|
||||
}
|
||||
|
||||
auto cacheKey = std::make_pair(resourceType, resourceName);
|
||||
decltype(m_ResourceCache)::iterator it;
|
||||
//If a thread has already been launched to load this resource.
|
||||
auto tIt = m_LoadingThreads.find(cacheKey);
|
||||
if (UseThreading && tIt != m_LoadingThreads.end()) {
|
||||
if (async) {
|
||||
//Throw StillLoadingException if the thread is still working.
|
||||
if (!tIt->second.try_join_for(boost::chrono::nanoseconds(1))) {
|
||||
throw Resource::StillLoadingException();
|
||||
}
|
||||
//Else we know the thread has completed.
|
||||
} else {
|
||||
//Wait for the thread to finish loading.
|
||||
tIt->second.join();
|
||||
}
|
||||
//When the thread is done, delete the thread.
|
||||
m_LoadingThreads.erase(tIt);
|
||||
//Rethrow the thread exception if it threw any.
|
||||
auto excIt = m_LoadingThreadExceptions.find(cacheKey);
|
||||
std::exception_ptr exception = excIt->second;
|
||||
m_LoadingThreadExceptions.erase(excIt);
|
||||
if (exception) {
|
||||
std::rethrow_exception(exception);
|
||||
}
|
||||
}
|
||||
|
||||
//If resource has already been cached and completely loaded.
|
||||
it = m_ResourceCache.find(cacheKey);
|
||||
if (it != m_ResourceCache.end()) {
|
||||
if (it->second != nullptr) {
|
||||
return static_cast<T*>(it->second);
|
||||
} else {
|
||||
//Don't return null on failure, exception instead.
|
||||
throw Resource::FailedLoadingException();
|
||||
}
|
||||
}
|
||||
|
||||
//If resource is not cached..
|
||||
if (UseThreading && async) {
|
||||
if (mustNotLoadInThread) {
|
||||
try {
|
||||
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
|
||||
} catch (const Resource::StillLoadingException&) {
|
||||
throw;
|
||||
}
|
||||
} else {
|
||||
//Create a thread that loads the resource into cache.
|
||||
m_LoadingThreads[cacheKey] = boost::thread(createResource, resourceType, resourceName, parent, m_LoadingThreadExceptions[cacheKey]);
|
||||
throw Resource::StillLoadingException();
|
||||
}
|
||||
} else {
|
||||
//load and return the resource.
|
||||
while (true) {
|
||||
try {
|
||||
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
|
||||
} catch (const Resource::StillLoadingException&) {
|
||||
continue;
|
||||
} catch (const std::exception&) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef Transform_h__
|
||||
#define Transform_h__
|
||||
|
||||
#include "../GLM.h"
|
||||
#include "World.h"
|
||||
|
||||
namespace Transform
|
||||
{
|
||||
|
||||
glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
||||
glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
||||
glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
||||
glm::mat4 ModelMatrix(EntityID entity, World* world);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,9 +9,8 @@
|
||||
#include "../Core/ConfigFile.h"
|
||||
#include "../Input/EInputCommand.h"
|
||||
#include "../Rendering/IRenderer.h"
|
||||
#include "../Rendering/EPicking.h"
|
||||
#include "../Core/Transform.h"
|
||||
#include "../Core/EFileDropped.h"
|
||||
#include "../Rendering/RenderQueueFactory.h"
|
||||
#include "../Core/EntityFilePreprocessor.h"
|
||||
#include "../Core/EntityFileParser.h"
|
||||
#include "../Core/EntityFileWriter.h"
|
||||
@@ -26,6 +25,7 @@ public:
|
||||
private:
|
||||
IRenderer* m_Renderer;
|
||||
World* m_World = nullptr;
|
||||
Camera* m_Camera = nullptr;
|
||||
|
||||
bool m_Enabled;
|
||||
bool m_Visible;
|
||||
@@ -57,6 +57,7 @@ private:
|
||||
EntityID m_WidgetOrigin = EntityID_Invalid;
|
||||
glm::vec3 m_WidgetCurrentAxis;
|
||||
float m_WidgetPickingDepth = 0.f;
|
||||
glm::vec3 m_WidgetPickingPosition = glm::vec3(0);
|
||||
|
||||
EntityID m_Selection = EntityID_Invalid;
|
||||
EntityID m_LastSelection = EntityID_Invalid;
|
||||
@@ -75,11 +76,10 @@ private:
|
||||
bool OnMousePress(const Events::MousePress& e);
|
||||
EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
|
||||
bool OnMouseMove(const Events::MouseMove& e);
|
||||
EventRelay<EditorSystem, Events::Picking> m_EPicking;
|
||||
bool OnPicking(const Events::Picking& e);
|
||||
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
|
||||
bool OnFileDropped(const Events::FileDropped& e);
|
||||
|
||||
|
||||
void Picking();
|
||||
void createWidget();
|
||||
void updateWidget();
|
||||
void setWidgetMode(WidgetMode newMode);
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
m_TexturePressed = resourceName;
|
||||
}
|
||||
|
||||
void Draw(RenderQueueCollection& rq) override
|
||||
void Draw(RenderScene& rq) override
|
||||
{
|
||||
if (m_Texture == nullptr && !m_TextureReleased.empty()) {
|
||||
SetTexture(m_TextureReleased);
|
||||
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
|
||||
virtual void Update(double dt) { }
|
||||
|
||||
void DrawLayered(RenderQueueCollection& rq)
|
||||
void DrawLayered(RenderScene& rq)
|
||||
{
|
||||
if (this->Hidden())
|
||||
return;
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Draw(RenderQueueCollection& rq) { }
|
||||
virtual void Draw(RenderScene& rq) { }
|
||||
|
||||
protected:
|
||||
::EventBroker* m_EventBroker;
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
void EnableScissor() { m_ScissorEnabled = true; }
|
||||
void DisableScissor() { m_ScissorEnabled = false; }
|
||||
|
||||
void Draw(RenderQueueCollection& rq) override
|
||||
void Draw(RenderScene& rq) override
|
||||
{
|
||||
if (m_Texture == nullptr)
|
||||
return;
|
||||
|
||||
@@ -23,7 +23,6 @@ public:
|
||||
~Client();
|
||||
void Start(World* world, EventBroker* eventBroker) override;
|
||||
void Update() override;
|
||||
void Close();
|
||||
private:
|
||||
// Assio UDP logic
|
||||
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
|
||||
@@ -32,7 +31,7 @@ private:
|
||||
|
||||
// Sending message to server logic
|
||||
int bytesRead = -1;
|
||||
char readBuf[1024] = { 0 };
|
||||
char readBuf[INPUTSIZE] = { 0 };
|
||||
int snapshotInterval = 33;
|
||||
std::clock_t previousSnapshotMessage = std::clock();
|
||||
|
||||
@@ -49,7 +48,6 @@ private:
|
||||
// Network logic
|
||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
||||
SnapshotDefinitions m_NextSnapshot;
|
||||
bool m_ThreadIsRunning = true;
|
||||
double m_DurationOfPingTime;
|
||||
std::clock_t m_StartPingTime;
|
||||
// Use to check if we should send disconnect message
|
||||
@@ -59,7 +57,7 @@ private:
|
||||
// Private member functions
|
||||
void readFromServer();
|
||||
void sendSnapshotToServer();
|
||||
int receive(char* data, size_t length);
|
||||
int receive(char* data, size_t length);
|
||||
void send(Packet& packet);
|
||||
void connect();
|
||||
void disconnect();
|
||||
@@ -67,6 +65,7 @@ private:
|
||||
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
|
||||
void parseMessageType(Packet& packet);
|
||||
void parseEventMessage(Packet& packet);
|
||||
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType);
|
||||
void parseConnect(Packet& packet);
|
||||
void parsePing();
|
||||
void parseServerPing();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "Network/Packet.h"
|
||||
|
||||
#define MAXCONNECTIONS 8
|
||||
#define INPUTSIZE 128
|
||||
#define INPUTSIZE 4097
|
||||
|
||||
class Network
|
||||
{
|
||||
|
||||
@@ -14,15 +14,17 @@ public:
|
||||
Packet(MessageType type, unsigned int& packetID);
|
||||
// Used to create packet from already existing data buffer.
|
||||
Packet(char* data, const int sizeOfPacket);
|
||||
|
||||
~Packet();
|
||||
void Init(MessageType type, unsigned int& packetID);
|
||||
|
||||
// Add primitive types like int, float, char...
|
||||
template<typename T>
|
||||
void WritePrimitive(T val)
|
||||
{
|
||||
// Check if we are trying to add more than the package can fit.
|
||||
if (m_MaxPacketSize < m_Offset + sizeof(T)) {
|
||||
LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!");
|
||||
LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for! New size is %i bytes\n", m_MaxPacketSize*2);
|
||||
resizeData();
|
||||
}
|
||||
memcpy(m_Data + m_Offset, &val, sizeof(T));
|
||||
m_Offset += sizeof(T);
|
||||
@@ -41,7 +43,7 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
// Add a string to the message
|
||||
void WriteString(std::string str);
|
||||
void WriteString(const std::string& str);
|
||||
// Add data to the message
|
||||
void WriteData(char* data, int sizeOfData);
|
||||
// Pops the first element as if it was a string.
|
||||
@@ -50,12 +52,15 @@ public:
|
||||
|
||||
int Size() { return m_Offset; };
|
||||
char* Data() { return m_Data; };
|
||||
unsigned int DataReadSize() { return m_ReturnDataOffset; }
|
||||
unsigned int MaxSize() { return m_MaxPacketSize; }
|
||||
|
||||
private:
|
||||
char* m_Data;
|
||||
unsigned int m_ReturnDataOffset = 0;
|
||||
int m_Offset = 0;
|
||||
unsigned int m_MaxPacketSize = 128;
|
||||
unsigned int m_MaxPacketSize = 512;
|
||||
void resizeData();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -20,8 +20,6 @@ public:
|
||||
~Server();
|
||||
void Start(World* m_world, EventBroker *eventBroker) override;
|
||||
void Update() override;
|
||||
void Close();
|
||||
|
||||
private:
|
||||
// UDP logic
|
||||
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
|
||||
@@ -30,7 +28,7 @@ private:
|
||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
||||
|
||||
// Sending messages to client logic
|
||||
char readBuffer[1024] = { 0 };
|
||||
char readBuffer[INPUTSIZE] = { 0 };
|
||||
int bytesRead = 0;
|
||||
// time for previouse message
|
||||
std::clock_t previousePingMessage = std::clock();
|
||||
@@ -55,9 +53,6 @@ private:
|
||||
unsigned int m_PacketID;
|
||||
unsigned int m_PreviousPacketID;
|
||||
unsigned int m_SendPacketID;
|
||||
|
||||
// Close logic
|
||||
bool m_ThreadIsRunning = true;
|
||||
|
||||
// Private member functions
|
||||
int receive(char* data, size_t length);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "../Core/ResourceManager.h"
|
||||
|
||||
class BaseTexture : public Resource
|
||||
class BaseTexture : public ThreadUnsafeResource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
|
||||
|
||||
@@ -26,13 +26,12 @@ public:
|
||||
glm::quat Orientation() const { return m_Orientation; }
|
||||
void SetOrientation(glm::quat val);
|
||||
|
||||
/*float Pitch() const { return m_Pitch; }
|
||||
void Pitch(float val);
|
||||
float Yaw() const { return m_Yaw; }
|
||||
void Yaw(float val);*/
|
||||
|
||||
glm::mat4 ProjectionMatrix() const { return m_ProjectionMatrix; }
|
||||
void SetProjectionMatrix(glm::mat4 val);
|
||||
|
||||
glm::mat4 ViewMatrix() const { return m_ViewMatrix; }
|
||||
void SetViewMatrix(glm::mat4 val);
|
||||
|
||||
|
||||
float AspectRatio() const { return m_AspectRatio; }
|
||||
void SetAspectRatio(float val);
|
||||
@@ -46,11 +45,10 @@ public:
|
||||
float FarClip() const { return m_FarClip; }
|
||||
void SetFarClip(float val);
|
||||
|
||||
|
||||
void UpdateViewMatrix();
|
||||
void UpdateProjectionMatrix();
|
||||
|
||||
private:
|
||||
void UpdateViewMatrix();
|
||||
void UpdateProjectionMatrix();
|
||||
|
||||
glm::vec3 m_Position;
|
||||
glm::quat m_Orientation;
|
||||
|
||||
@@ -9,6 +9,9 @@ public:
|
||||
: FirstPersonInputController(eventBroker, playerID)
|
||||
{ }
|
||||
|
||||
void SetPosition(const glm::vec3 position) { m_Position = position; }
|
||||
void SetOrientation(const glm::quat orientation) { m_Orientation = orientation; }
|
||||
|
||||
const glm::vec3 Position() const { return m_Position; }
|
||||
void SetBaseSpeed(float speed) { m_BaseSpeed = speed; }
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef DrawFinalPass_h__
|
||||
#define DrawFinalPass_h__
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "DrawFinalPassState.h"
|
||||
#include "LightCullingPass.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Util/UnorderedMapVec2.h"
|
||||
#include "Texture.h"
|
||||
|
||||
class DrawFinalPass
|
||||
{
|
||||
public:
|
||||
DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass);
|
||||
~DrawFinalPass() { }
|
||||
void InitializeTextures();
|
||||
void InitializeFrameBuffers();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
void Draw(RenderScene& scene);
|
||||
|
||||
//Getters
|
||||
|
||||
|
||||
private:
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
||||
|
||||
Texture* m_WhiteTexture;
|
||||
|
||||
const IRenderer* m_Renderer;
|
||||
const LightCullingPass* m_LightCullingPass;
|
||||
|
||||
ShaderProgram* m_ForwardPlusProgram;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef DrawFinalPassState_h__
|
||||
#define DrawFinalPassState_h__
|
||||
|
||||
#include "Rendering/RenderState.h"
|
||||
|
||||
class DrawFinalPassState : public RenderState
|
||||
{
|
||||
public:
|
||||
DrawFinalPassState();
|
||||
~DrawFinalPassState();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
void InitializeFrameBuffers();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
void Draw(RenderQueueCollection& rq);
|
||||
void Draw(RenderScene& scene);
|
||||
|
||||
//Getters
|
||||
|
||||
@@ -25,12 +25,18 @@ public:
|
||||
private:
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
||||
|
||||
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j)
|
||||
{
|
||||
return (i->Depth < j->Depth);
|
||||
};
|
||||
|
||||
Texture* m_WhiteTexture;
|
||||
|
||||
const IRenderer* m_Renderer;
|
||||
|
||||
ShaderProgram* m_BasicForwardProgram;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,7 @@ class DummyRenderer : public IRenderer
|
||||
{
|
||||
public:
|
||||
virtual void Initialize() override;
|
||||
virtual void Draw(RenderQueueCollection& rq) override;
|
||||
virtual void Draw(RenderFrame& rq) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
#ifndef Events_Picking_h__
|
||||
#define Events_Picking_h__
|
||||
|
||||
#include "../OpenGL.h"
|
||||
#include "../GLM.h"
|
||||
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "Util/ScreenCoords.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "../Core/Entity.h"
|
||||
#include "Util/UnorderedMapVec2.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
/** Thrown Every frame, use functions to pick*/
|
||||
struct Picking : Event
|
||||
{
|
||||
public:
|
||||
Picking(FrameBuffer* pickingBuffer, GLuint* depthBuffer, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, Rectangle resolution, const std::unordered_map<glm::vec2, EntityID>* pickingColorsToEntity)
|
||||
: PickingBuffer(pickingBuffer)
|
||||
, DepthBuffer(depthBuffer)
|
||||
, ProjectionMatrix(projectionMatrix)
|
||||
, ViewMatrix(viewMatrix)
|
||||
, Resolution(resolution)
|
||||
, PickingColorsToEntity(pickingColorsToEntity)
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
struct PickData
|
||||
{
|
||||
//Picked Entity
|
||||
EntityID Entity;
|
||||
//World position of the "pick"
|
||||
glm::vec3 Position;
|
||||
// Depth
|
||||
float Depth;
|
||||
};
|
||||
|
||||
PickData Pick(glm::vec2 screenCoord) const
|
||||
{
|
||||
PickData pickData;
|
||||
|
||||
// Invert screen y coordinate
|
||||
screenCoord.y = Resolution.Height - screenCoord.y;
|
||||
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
|
||||
pickData.Depth = data.Depth;
|
||||
|
||||
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
|
||||
if (it != PickingColorsToEntity->end()) {
|
||||
pickData.Entity = it->second;
|
||||
} else {
|
||||
pickData.Entity = EntityID_Invalid;
|
||||
}
|
||||
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
|
||||
|
||||
return pickData;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
FrameBuffer* PickingBuffer;
|
||||
GLuint* DepthBuffer;
|
||||
const glm::mat4 ProjectionMatrix;
|
||||
const glm::mat4 ViewMatrix;
|
||||
const Rectangle Resolution;
|
||||
const std::unordered_map<glm::vec2, EntityID>* PickingColorsToEntity;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef Events_SetCamera_h__
|
||||
#define Events_SetCamera_h__
|
||||
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "../Core/Entity.h"
|
||||
#include <string.h>
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct SetCamera : Event
|
||||
{
|
||||
public:
|
||||
SetCamera() { };
|
||||
std::string Name;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,6 +9,17 @@
|
||||
#include "Camera.h"
|
||||
#include "RenderQueue.h"
|
||||
#include "Model.h"
|
||||
#include "../Core/World.h" //So temp
|
||||
|
||||
|
||||
struct PickData
|
||||
{
|
||||
EntityID Entity;
|
||||
glm::vec3 Position; //World position
|
||||
float Depth;
|
||||
::Camera* Camera;
|
||||
const ::World* World;
|
||||
};
|
||||
|
||||
class IRenderer
|
||||
{
|
||||
@@ -20,19 +31,21 @@ public:
|
||||
void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; }
|
||||
bool VSYNC() const { return m_VSYNC; }
|
||||
void SetVSYNC(bool vsync) { m_VSYNC = vsync; }
|
||||
::Camera* Camera() const { return m_Camera; }
|
||||
void SetCamera(::Camera* camera)
|
||||
{
|
||||
if (camera == nullptr) {
|
||||
m_Camera = m_DefaultCamera;
|
||||
} else {
|
||||
m_Camera = camera;
|
||||
}
|
||||
}
|
||||
|
||||
::Camera* Camera() const { return m_Camera; }
|
||||
void SetCamera(::Camera* camera)
|
||||
{
|
||||
if (camera == nullptr) {
|
||||
m_Camera = m_DefaultCamera;
|
||||
} else {
|
||||
m_Camera = camera;
|
||||
}
|
||||
}
|
||||
virtual void Initialize() = 0;
|
||||
virtual void Update(double dt) = 0;
|
||||
virtual void Draw(RenderQueueCollection& rq) = 0;
|
||||
virtual void Draw(RenderFrame& rq) = 0;
|
||||
virtual PickData Pick(glm::vec2 screenCord) = 0;
|
||||
|
||||
World* m_World; //Temp world, untill viktor merge.
|
||||
|
||||
protected:
|
||||
Rectangle m_Resolution = Rectangle::Rectangle(1280, 720);
|
||||
@@ -40,9 +53,9 @@ protected:
|
||||
bool m_VSYNC = false;
|
||||
int m_GLVersion[2];
|
||||
std::string m_GLVendor;
|
||||
::Camera* m_DefaultCamera;
|
||||
::Camera* m_Camera = nullptr;
|
||||
GLFWwindow* m_Window = nullptr;
|
||||
::Camera* m_DefaultCamera;
|
||||
::Camera* m_Camera = nullptr;
|
||||
};
|
||||
|
||||
#endif // Renderer_h__
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef LightCullingPass_h__
|
||||
#define LightCullingPass_h__
|
||||
|
||||
#define TILE_SIZE 16
|
||||
#define MAX_LIGHTS_PER_TILE 200
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "LightCullingPassState.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "RenderQueue.h"
|
||||
|
||||
|
||||
class LightCullingPass
|
||||
{
|
||||
public:
|
||||
LightCullingPass(IRenderer* renderer);
|
||||
~LightCullingPass();
|
||||
|
||||
void GenerateNewFrustum(RenderScene& scene);
|
||||
void OnResolutionChange();
|
||||
void SetSSBOSizes();
|
||||
void CullLights(RenderScene& scene);
|
||||
void FillLightList(RenderScene& scene);
|
||||
|
||||
GLuint FrustumSSBO() const { return m_FrustumSSBO; }
|
||||
GLuint LightSSBO() const { return m_LightSSBO; }
|
||||
GLuint LightGridSSBO() const { return m_LightGridSSBO; }
|
||||
GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; }
|
||||
GLuint LightIndexSSBO() const { return m_LightIndexSSBO; }
|
||||
private:
|
||||
|
||||
void InitializeSSBOs();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
const IRenderer* m_Renderer;
|
||||
|
||||
GLuint m_FrustumSSBO = 0;
|
||||
GLuint m_LightSSBO = 0;
|
||||
GLuint m_LightGridSSBO = 0;
|
||||
GLuint m_LightOffsetSSBO = 0;
|
||||
GLuint m_LightIndexSSBO = 0;
|
||||
|
||||
ShaderProgram* m_CalculateFrustumProgram;
|
||||
ShaderProgram* m_LightCullProgram;
|
||||
|
||||
int m_NumberOfTiles = 0;
|
||||
|
||||
struct Plane {
|
||||
glm::vec3 Normal;
|
||||
float d;
|
||||
};
|
||||
|
||||
struct Frustum {
|
||||
Plane Planes[4];
|
||||
};
|
||||
Frustum* m_Frustums;
|
||||
|
||||
//This should be a component
|
||||
struct PointLight {
|
||||
glm::vec4 Position = glm::vec4(0.f);
|
||||
glm::vec4 Color = glm::vec4(1.f);
|
||||
float Radius = 5.f;
|
||||
float Intensity = 0.8f;
|
||||
float Falloff = 0.3f;
|
||||
float Padding = 1337;
|
||||
};
|
||||
std::vector<PointLight> m_PointLights;
|
||||
|
||||
struct LightGrid {
|
||||
float Start;
|
||||
float Amount;
|
||||
glm::vec2 Padding;
|
||||
};
|
||||
|
||||
LightGrid* m_LightGrid;
|
||||
|
||||
int m_LightOffset = 0;
|
||||
|
||||
float* m_LightIndex;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "RawModelAssimp.h"
|
||||
#include "../OpenGL.h"
|
||||
|
||||
class Model : public RawModel
|
||||
class Model : public ThreadUnsafeResource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
|
||||
@@ -13,11 +13,15 @@ private:
|
||||
|
||||
public:
|
||||
~Model();
|
||||
const std::vector<RawModel::MaterialGroup>& MaterialGroups() const { return m_RawModel->MaterialGroups; }
|
||||
const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; }
|
||||
const std::vector<RawModel::Vertex>& Vertices() const { return m_RawModel->m_Vertices; }
|
||||
|
||||
GLuint VAO;
|
||||
GLuint ElementBuffer;
|
||||
|
||||
private:
|
||||
RawModel* m_RawModel;
|
||||
GLuint VertexBuffer;
|
||||
GLuint DiffuseVertexColorBuffer;
|
||||
GLuint SpecularVertexColorBuffer;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef ModelJob_h__
|
||||
#define ModelJob_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../GLM.h"
|
||||
#include "../Core/ComponentWrapper.h"
|
||||
#include "Texture.h"
|
||||
#include "Model.h"
|
||||
#include "RenderJob.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "Camera.h"
|
||||
#include "../Core/World.h"
|
||||
|
||||
struct ModelJob : RenderJob
|
||||
{
|
||||
ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world)
|
||||
: RenderJob()
|
||||
{
|
||||
Model = model;
|
||||
TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0;
|
||||
DiffuseTexture = matGroup.Texture.get();
|
||||
NormalTexture = matGroup.NormalMap.get();
|
||||
SpecularTexture = matGroup.SpecularMap.get();
|
||||
StartIndex = matGroup.StartIndex;
|
||||
EndIndex = matGroup.EndIndex;
|
||||
Matrix = matrix;
|
||||
Color = modelComponent["Color"];
|
||||
Entity = modelComponent.EntityID;
|
||||
World = world;
|
||||
};
|
||||
|
||||
unsigned int TextureID;
|
||||
unsigned int ShaderID;
|
||||
|
||||
EntityID Entity;
|
||||
glm::mat4 Matrix;
|
||||
const Texture* DiffuseTexture;
|
||||
const Texture* NormalTexture;
|
||||
const Texture* SpecularTexture;
|
||||
float Shininess = 0.f;
|
||||
glm::vec4 Color;
|
||||
const ::Model* Model = nullptr;
|
||||
unsigned int StartIndex = 0;
|
||||
unsigned int EndIndex = 0;
|
||||
World* World;
|
||||
|
||||
void CalculateHash() override
|
||||
{
|
||||
Hash = TextureID;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,13 +1,17 @@
|
||||
#ifndef PickingPass_h__
|
||||
#define PickingPass_h__
|
||||
|
||||
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "PickingPassState.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Util/UnorderedMapVec2.h"
|
||||
#include "Util/UnorderedMapiVec2.h"
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "EPicking.h"
|
||||
#include "../Core/World.h"
|
||||
|
||||
|
||||
|
||||
class PickingPass
|
||||
{
|
||||
@@ -18,16 +22,18 @@ public:
|
||||
void InitializeFrameBuffers();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
void Draw(RenderQueueCollection& rq);
|
||||
|
||||
void Draw(RenderScene& scene);
|
||||
void ClearPicking();
|
||||
|
||||
//Getters
|
||||
const ShaderProgram& PickingProgram() const { return *m_PickingProgram; }
|
||||
const std::unordered_map<glm::vec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
|
||||
//const std::unordered_map<glm::ivec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
|
||||
GLuint PickingTexture() const { return m_PickingTexture; }
|
||||
GLuint DepthBuffer() const { return m_DepthBuffer; }
|
||||
const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; }
|
||||
|
||||
|
||||
PickData Pick(glm::vec2 screenCoord);
|
||||
|
||||
private:
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
||||
@@ -37,13 +43,24 @@ private:
|
||||
const IRenderer* m_Renderer;
|
||||
|
||||
ShaderProgram* m_PickingProgram;
|
||||
Camera* m_Camera;
|
||||
|
||||
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
|
||||
struct PickingInfo
|
||||
{
|
||||
EntityID Entity;
|
||||
const ::World* World;
|
||||
::Camera* Camera;
|
||||
};
|
||||
|
||||
std::unordered_map<glm::ivec2, PickingInfo> m_PickingColorsToEntity;
|
||||
|
||||
GLuint m_PickingTexture;
|
||||
GLuint m_DepthBuffer;
|
||||
|
||||
FrameBuffer m_PickingBuffer;
|
||||
|
||||
int m_ColorCounter[2];
|
||||
std::map<std::tuple<EntityID, const World*, Camera*>, glm::ivec2> m_EntityColors;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef PointLightJob_h__
|
||||
#define PointLightJob_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../GLM.h"
|
||||
#include "../Core/ComponentWrapper.h"
|
||||
#include "RenderJob.h"
|
||||
#include "../Core/Transform.h"
|
||||
#include "../Core/World.h"
|
||||
|
||||
struct PointLightJob : RenderJob
|
||||
{
|
||||
PointLightJob(ComponentWrapper transformComponent, ComponentWrapper pointLightComponent, World* m_World)
|
||||
: RenderJob()
|
||||
{
|
||||
Position = glm::vec4((glm::vec3)transformComponent["Position"], 1.0f);
|
||||
Position = glm::vec4(Transform::AbsolutePosition(m_World, transformComponent.EntityID), 1.f);
|
||||
Color = (glm::vec4)pointLightComponent["Color"];
|
||||
Radius = (double)pointLightComponent["Radius"];
|
||||
Intensity = (double)pointLightComponent["Intensity"];
|
||||
Falloff = (double)pointLightComponent["Falloff"];
|
||||
};
|
||||
|
||||
glm::vec4 Position;
|
||||
glm::vec4 Color;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float Falloff;
|
||||
float padding = 123;
|
||||
|
||||
void CalculateHash() override
|
||||
{
|
||||
Hash = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -42,14 +42,18 @@ public:
|
||||
struct MaterialGroup
|
||||
{
|
||||
float Shininess;
|
||||
float Transparency;
|
||||
std::string TexturePath;
|
||||
std::shared_ptr<::Texture> Texture;
|
||||
std::string NormalMapPath;
|
||||
std::shared_ptr<::Texture> NormalMap;
|
||||
std::string SpecularMapPath;
|
||||
std::shared_ptr<::Texture> SpecularMap;
|
||||
unsigned int StartIndex;
|
||||
unsigned int EndIndex;
|
||||
};
|
||||
|
||||
std::vector<MaterialGroup> TextureGroups;
|
||||
std::vector<MaterialGroup> MaterialGroups;
|
||||
|
||||
std::vector<Vertex> m_Vertices;
|
||||
std::vector<unsigned int> m_Indices;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef RenderJob_h__
|
||||
#define RenderJob_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../GLM.h"
|
||||
#include "../Core/ComponentWrapper.h"
|
||||
#include "RenderQueue.h"
|
||||
|
||||
|
||||
struct RenderJob
|
||||
{
|
||||
friend class RenderQueue;
|
||||
|
||||
public:
|
||||
|
||||
float Depth;
|
||||
|
||||
protected:
|
||||
uint64_t Hash;
|
||||
|
||||
virtual void CalculateHash() = 0;
|
||||
|
||||
bool operator<(const RenderJob& rhs)
|
||||
{
|
||||
return this->Hash < rhs.Hash;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,61 +8,13 @@
|
||||
#include "../GLM.h"
|
||||
#include "../Core/Util/Rectangle.h"
|
||||
#include "../Core/Entity.h"
|
||||
#include "Camera.h"
|
||||
#include "RenderJob.h"
|
||||
#include "ModelJob.h"
|
||||
#include "PointLightJob.h"
|
||||
|
||||
class Model;
|
||||
class Skeleton;
|
||||
class Texture;
|
||||
class RenderQueue;
|
||||
|
||||
//TODO: Render: Remove obsolete RenderJobs and fix standard values on variables.
|
||||
|
||||
struct RenderJob
|
||||
{
|
||||
friend class RenderQueue;
|
||||
|
||||
float Depth;
|
||||
|
||||
protected:
|
||||
uint64_t Hash;
|
||||
|
||||
virtual void CalculateHash() = 0;
|
||||
|
||||
bool operator<(const RenderJob& rhs)
|
||||
{
|
||||
return this->Hash < rhs.Hash;
|
||||
}
|
||||
};
|
||||
|
||||
struct ModelJob : RenderJob
|
||||
{
|
||||
unsigned int ShaderID = 0;
|
||||
unsigned int TextureID = 0;
|
||||
|
||||
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
|
||||
EntityID Entity;
|
||||
|
||||
glm::mat4 ModelMatrix;
|
||||
const Texture* DiffuseTexture;
|
||||
const Texture* NormalTexture;
|
||||
const Texture* SpecularTexture;
|
||||
float Shininess = 0.f;
|
||||
glm::vec4 Color;
|
||||
const Model* Model = nullptr;
|
||||
unsigned int StartIndex = 0;
|
||||
unsigned int EndIndex = 0;
|
||||
|
||||
// Animation
|
||||
Skeleton* Skeleton = nullptr;
|
||||
bool NoRootMotion = true;
|
||||
std::string AnimationName;
|
||||
double AnimationTime = 0;
|
||||
|
||||
void CalculateHash() override
|
||||
{
|
||||
Hash = TextureID;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
struct SpriteJob : RenderJob
|
||||
{
|
||||
unsigned int ShaderID = 0;
|
||||
@@ -82,73 +34,65 @@ struct SpriteJob : RenderJob
|
||||
|
||||
struct PointLightJob : RenderJob
|
||||
{
|
||||
glm::vec3 Position;
|
||||
glm::vec3 SpecularColor = glm::vec3(1, 1, 1);
|
||||
glm::vec3 DiffuseColor = glm::vec3(1, 1, 1);
|
||||
float Radius = 1.f;
|
||||
float Intensity = 0.8f;
|
||||
glm::vec4 Position;
|
||||
glm::vec4 Color;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float Falloff;
|
||||
float padding = 123;
|
||||
|
||||
void CalculateHash() override
|
||||
{
|
||||
Hash = 0;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
class RenderQueue
|
||||
struct RenderScene
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
void Add(T &job)
|
||||
{
|
||||
job.CalculateHash();
|
||||
Jobs.push_back(std::shared_ptr<T>(new T(job)));
|
||||
m_Size++;
|
||||
}
|
||||
|
||||
void Sort()
|
||||
{
|
||||
Jobs.sort();
|
||||
}
|
||||
::Camera* Camera;
|
||||
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
|
||||
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
|
||||
Rectangle Viewport;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Jobs.clear();
|
||||
m_Size = 0;
|
||||
ForwardJobs.clear();
|
||||
PointLightJobs.clear();
|
||||
}
|
||||
|
||||
int Size() const { return m_Size; }
|
||||
std::list<std::shared_ptr<RenderJob>>::const_iterator begin()
|
||||
{
|
||||
return Jobs.begin();
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<RenderJob>>::const_iterator end()
|
||||
{
|
||||
return Jobs.end();
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<RenderJob>> Jobs;
|
||||
|
||||
private:
|
||||
int m_Size = 0;
|
||||
};
|
||||
|
||||
struct RenderQueueCollection
|
||||
struct RenderFrame
|
||||
{
|
||||
RenderQueue Forward;
|
||||
RenderQueue Lights;
|
||||
public:
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Forward.Clear();
|
||||
Lights.Clear();
|
||||
}
|
||||
void Add(RenderScene &scene)
|
||||
{
|
||||
RenderScenes.push_back(std::shared_ptr<RenderScene>(new RenderScene(scene)));
|
||||
m_Size++;
|
||||
}
|
||||
|
||||
void Sort()
|
||||
{
|
||||
Forward.Sort();
|
||||
Lights.Sort();
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
RenderScenes.clear();
|
||||
m_Size = 0;
|
||||
}
|
||||
|
||||
int Size() const { return m_Size; }
|
||||
std::list<std::shared_ptr<RenderScene>>::const_iterator begin()
|
||||
{
|
||||
return RenderScenes.begin();
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<RenderScene>>::const_iterator end()
|
||||
{
|
||||
return RenderScenes.end();
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<RenderScene>> RenderScenes;
|
||||
|
||||
private:
|
||||
int m_Size = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef RenderQueueFactory_h__
|
||||
#define RenderQueueFactory_h__
|
||||
|
||||
#include "../Core/World.h"
|
||||
#include "RenderQueue.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "Model.h"
|
||||
#include "../GLM.h"
|
||||
|
||||
class RenderQueueFactory
|
||||
{
|
||||
public:
|
||||
RenderQueueFactory();
|
||||
void Update(World* world);
|
||||
|
||||
RenderQueueCollection RenderQueues() const { return m_RenderQueues; }
|
||||
|
||||
static glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
||||
static glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
||||
static glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
||||
|
||||
private:
|
||||
RenderQueueCollection m_RenderQueues;
|
||||
|
||||
void FillModels(World* world, RenderQueue* renderQueue);
|
||||
void FillLights(World* world, RenderQueue* renderQueue);
|
||||
|
||||
glm::mat4 ModelMatrix(World* world, EntityID entity);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef RenderSystem_h__
|
||||
#define RenderSystem_h__
|
||||
|
||||
#include "../Core/System.h"
|
||||
#include "RenderQueue.h"
|
||||
#include "../GLM.h"
|
||||
#include "../OpenGL.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "ESetCamera.h"
|
||||
#include "Model.h"
|
||||
#include "../Core/EKeyDown.h"
|
||||
#include "../Input/EInputCommand.h"
|
||||
#include "Camera.h"
|
||||
#include "ModelJob.h"
|
||||
#include "Renderer.h"
|
||||
#include "PointLightJob.h"
|
||||
#include "../Core/Transform.h"
|
||||
#include "DebugCameraInputController.h"
|
||||
|
||||
class RenderSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
RenderSystem(EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame);
|
||||
~RenderSystem();
|
||||
|
||||
virtual void Update(World* world, double dt) override;
|
||||
|
||||
private:
|
||||
World* m_World = nullptr;
|
||||
const IRenderer* m_Renderer;
|
||||
|
||||
RenderFrame* m_RenderFrame;
|
||||
bool m_SwitchCamera = false;
|
||||
Camera* m_Camera;
|
||||
DebugCameraInputController<RenderSystem>* m_DebugCameraInputController;
|
||||
|
||||
std::list<ComponentWrapper> m_CameraComponents;
|
||||
|
||||
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
|
||||
bool OnSetCamera(const Events::SetCamera &event);
|
||||
EntityID m_CurrentCamera = EntityID_Invalid;
|
||||
|
||||
void switchCamera(EntityID entity);
|
||||
|
||||
void updateCamera(World* world, double dt);
|
||||
void updateProjectionMatrix(ComponentWrapper& cameraComponent);
|
||||
|
||||
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
||||
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
||||
|
||||
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -12,45 +12,34 @@
|
||||
#include "../Core/World.h"
|
||||
#include "PickingPass.h"
|
||||
#include "DrawScenePass.h"
|
||||
#include "DebugCameraInputController.h"
|
||||
|
||||
|
||||
#define TILE_SIZE 16
|
||||
#define NUM_LIGHTS 3
|
||||
|
||||
|
||||
enum lightType
|
||||
{
|
||||
Point,
|
||||
Spot,
|
||||
Directional,
|
||||
Area
|
||||
};
|
||||
|
||||
#include "LightCullingPass.h"
|
||||
#include "DrawFinalPass.h"
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "EPicking.h"
|
||||
#include "ImGuiRenderPass.h"
|
||||
#include "Camera.h"
|
||||
#include "../Core/Transform.h"
|
||||
|
||||
class Renderer : public IRenderer
|
||||
{
|
||||
public:
|
||||
Renderer(EventBroker* eventBroker)
|
||||
Renderer(EventBroker* eventBroker, World* world)
|
||||
: m_EventBroker(eventBroker)
|
||||
, m_World(world)
|
||||
{ }
|
||||
|
||||
virtual void Initialize() override;
|
||||
virtual void Update(double dt) override;
|
||||
virtual void Draw(RenderQueueCollection& rq) override;
|
||||
virtual void Draw(RenderFrame& frame) override;
|
||||
|
||||
virtual PickData Pick(glm::vec2 screenCoord) override;
|
||||
|
||||
private:
|
||||
//----------------------Variables----------------------//
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
std::shared_ptr<DebugCameraInputController<Renderer>> m_DebugCameraInputController;
|
||||
World* m_World;
|
||||
|
||||
Texture* m_ErrorTexture;
|
||||
Texture* m_WhiteTexture;
|
||||
float m_CameraMoveSpeed;
|
||||
|
||||
Model* m_ScreenQuad;
|
||||
Model* m_UnitQuad;
|
||||
@@ -58,70 +47,26 @@ private:
|
||||
|
||||
DrawScenePass* m_DrawScenePass;
|
||||
PickingPass* m_PickingPass;
|
||||
LightCullingPass* m_LightCullingPass;
|
||||
ImGuiRenderPass* m_ImGuiRenderPass;
|
||||
DrawFinalPass* m_DrawFinalPass;
|
||||
|
||||
//----------------------Functions----------------------//
|
||||
void InitializeWindow();
|
||||
void InitializeShaders();
|
||||
void InitializeTextures();
|
||||
void InitializeSSBOs();
|
||||
void InitializeRenderPasses();
|
||||
//TODO: Renderer: Get InputUpdate out of renderer
|
||||
void InputUpdate(double dt);
|
||||
//void PickingPass(RenderQueueCollection& rq);
|
||||
void DrawScreenQuad(GLuint textureToDraw);
|
||||
|
||||
//----------------------Forward+-----------------------//
|
||||
void CalculateFrustum();
|
||||
void CullLights();
|
||||
//Frustum
|
||||
struct Plane {
|
||||
glm::vec3 Normal;
|
||||
float d;
|
||||
};
|
||||
struct Frustum {
|
||||
Plane Planes[4];
|
||||
};
|
||||
Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution
|
||||
|
||||
//Lights
|
||||
void TEMPCreateLights();
|
||||
//TODO: Renderer: Add Directionllights, spotlights and area lights to this as type.
|
||||
struct PointLight {
|
||||
glm::vec4 Position = glm::vec4(0.f);
|
||||
glm::vec4 Color = glm::vec4(1.f);
|
||||
float Radius = 5.f;
|
||||
float Intensity = 0.8f;
|
||||
float Falloff = 0.3f;
|
||||
float Padding = 1337;
|
||||
};
|
||||
PointLight m_PointLights[NUM_LIGHTS];
|
||||
|
||||
struct LightGrid {
|
||||
int Amount;
|
||||
int Start;
|
||||
glm::vec2 Padding;
|
||||
};
|
||||
LightGrid m_LightGrid[80*45];
|
||||
|
||||
int m_LightOffset = 0;
|
||||
|
||||
int m_LightIndex[80*45*200];
|
||||
|
||||
//-------------------------SSBO------------------------//
|
||||
GLuint m_FrustumSSBO = 0;
|
||||
GLuint m_LightSSBO = 1;
|
||||
GLuint m_LightGridSSBO = 2;
|
||||
GLuint m_LightOffsetSSBO = 3;
|
||||
GLuint m_LightIndexSSBO = 4;
|
||||
|
||||
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j) { return (i->Depth < j->Depth); }
|
||||
void FillDepth(RenderScene& scene);
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
|
||||
//--------------------ShaderPrograms-------------------//
|
||||
ShaderProgram* m_BasicForwardProgram;
|
||||
ShaderProgram* m_DrawScreenQuadProgram;
|
||||
ShaderProgram* m_CalculateFrustumProgram;
|
||||
ShaderProgram* m_LightCullProgram;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#ifndef UnorderedMapiVec2_h__
|
||||
#define UnorderedMapiVec2_h__
|
||||
|
||||
#include <functional>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
template<>
|
||||
struct std::hash<glm::ivec2>
|
||||
{
|
||||
inline std::size_t operator()(const glm::ivec2 &v) const
|
||||
{
|
||||
return boost::hash<float>()(v.x) ^ boost::hash<float>()(v.y);
|
||||
}
|
||||
|
||||
inline bool operator()(const glm::ivec2& a, const glm::ivec2& b)const
|
||||
{
|
||||
return a.x == b.x && a.y == b.y;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef Events_ContinueSound_h__
|
||||
#define Events_ContinueSound_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
// Continues to play a sound from where it was paused.
|
||||
struct ContinueSound : Event
|
||||
{
|
||||
EntityID EmitterID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef Events_PauseSound_h__
|
||||
#define Events_PauseSound_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
// Pauses a playing sound
|
||||
struct PauseSound : Event
|
||||
{
|
||||
EntityID EmitterID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef Events_PlayBackgroundMusic_h__
|
||||
#define Events_PlayBackgroundMusic_h__
|
||||
|
||||
#include <string>
|
||||
#include "Core/Entity.h"
|
||||
#include "Core/Event.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
// Play a sound that will be heared the same anywhere
|
||||
struct PlayBackgroundMusic : public Event
|
||||
{
|
||||
std::string FilePath = "";
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef Events_PlaySoundOnEntity_h__
|
||||
#define Events_PlaySoundOnEntity_h__
|
||||
|
||||
#include <string>
|
||||
#include "Core/Entity.h"
|
||||
#include "Core/Event.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
// Plays a sound on an entity with a SoundEmitter component attached.
|
||||
// Sound behavior is thereby specified in the SoundEmitter component.
|
||||
struct PlaySoundOnEntity : public Event
|
||||
{
|
||||
EntityID EmitterID = 0;
|
||||
std::string FilePath = "";
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef Events_PlaySoundOnPosition_h__
|
||||
#define Events_PlaySoundOnPosition_h__
|
||||
|
||||
#include <string>
|
||||
#include <glm/common.hpp>
|
||||
#include "Core/Event.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
// Plays a sound on a given position. Idk if this would be useful.
|
||||
struct PlaySoundOnPosition : public Event
|
||||
{
|
||||
glm::vec3 Position = glm::vec3(0);
|
||||
std::string FilePath = "";
|
||||
float Gain = 1;
|
||||
float Pitch = 1;
|
||||
bool Loop = false;
|
||||
float MaxDistance = 20;
|
||||
float RollOffFactor = 1;
|
||||
float ReferenceDistance = 1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef Events_SetBGMGain_h__
|
||||
#define Events_SetBGMGain_h__
|
||||
|
||||
#include "Core/Event.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
// Set the "volume" for all background sounds
|
||||
struct SetBGMGain : public Event
|
||||
{
|
||||
float Gain;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef Events_SetSFXGain_h__
|
||||
#define Events_SetSFXGain_h__
|
||||
|
||||
#include "Core/Event.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
// Set the "volume" for all effect sounds
|
||||
struct SetSFXGain : public Event
|
||||
{
|
||||
float Gain;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef Events_StopSound_h__
|
||||
#define Events_StopSound_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
// Stops a sound emitter, and will also delete it.
|
||||
struct StopSound : Event
|
||||
{
|
||||
EntityID EmitterID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
#ifndef Sound_h__
|
||||
#define Sound_h__
|
||||
|
||||
#include "Core/ResourceManager.h"
|
||||
|
||||
class Sound : public Resource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
public:
|
||||
Sound(std::string path) { m_Buffer = LoadFile(path); m_Path = path; }
|
||||
~Sound() { ClearBuffer(); }
|
||||
ALuint Buffer() { return m_Buffer; }
|
||||
std::string Path() { return m_Path; }
|
||||
float Gain() { return m_Gain; }
|
||||
void SetGain(float value) { m_Gain = value; }
|
||||
void ClearBuffer() { alDeleteBuffers(1, &m_Buffer); m_BufferCache.clear(); };
|
||||
|
||||
private:
|
||||
float m_Gain = 1;
|
||||
ALuint m_Buffer;
|
||||
std::string m_Path;
|
||||
|
||||
// File info
|
||||
char m_Type[4];
|
||||
unsigned long m_Size, m_ChunkSize;
|
||||
short m_FormatType, m_Channels;
|
||||
unsigned long m_SampleRate, m_AvgBytesPerSec;
|
||||
short m_BytesPerSample, m_BitsPerSample;
|
||||
unsigned int m_DataSize;
|
||||
std::map<std::string, ALuint> m_BufferCache;
|
||||
|
||||
ALuint LoadFile(std::string path)
|
||||
{
|
||||
if (m_BufferCache.find(path) != m_BufferCache.end()) {
|
||||
return m_BufferCache[path];
|
||||
}
|
||||
|
||||
// Open file
|
||||
FILE *fp = fopen(path.c_str(), "rb");
|
||||
if (!fp) {
|
||||
printf("Sound: Failed to open file %s, no such file exists", path.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
//CHECK FOR VALID WAVE-FILE
|
||||
fread(m_Type, sizeof(char), 4, fp);
|
||||
if (m_Type[0] != 'R' || m_Type[1] != 'I' || m_Type[2] != 'F' || m_Type[3] != 'F') {
|
||||
printf("ERROR: No RIFF in WAVE-file");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fread(&m_Size, 4 * sizeof(char), 1, fp);
|
||||
fread(m_Type, sizeof(char), 4, fp);
|
||||
if (m_Type[0] != 'W' || m_Type[1] != 'A' || m_Type[2] != 'V' || m_Type[3] != 'E') {
|
||||
printf("ERROR: Not WAVE-file");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fread(m_Type, sizeof(char), 4, fp);
|
||||
if (m_Type[0] != 'f' || m_Type[1] != 'm' || m_Type[2] != 't' || m_Type[3] != ' ') {
|
||||
printf("ERROR: No fmt in WAVE-file");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// READ THE DATA FROM WAVE-FILE
|
||||
fread(&m_ChunkSize, 4 * sizeof(char), 1, fp);
|
||||
fread(&m_FormatType, 2 * sizeof(char), 1, fp);
|
||||
fread(&m_Channels, 2 * sizeof(char), 1, fp);
|
||||
fread(&m_SampleRate, 4 * sizeof(char), 1, fp);
|
||||
fread(&m_AvgBytesPerSec, 4 * sizeof(char), 1, fp);
|
||||
fread(&m_BytesPerSample, 2 * sizeof(char), 1, fp);
|
||||
fread(&m_BitsPerSample, 2 * sizeof(char), 1, fp);
|
||||
|
||||
fread(m_Type, sizeof(char), 4, fp);
|
||||
if (m_Type[0] != 'd' || m_Type[1] != 'a' || m_Type[2] != 't' || m_Type[3] != 'a') {
|
||||
printf("ERROR: WAVE-file Missing data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fread(&m_DataSize, 4 * sizeof(char), 1, fp);
|
||||
|
||||
unsigned char* buf = new unsigned char[m_DataSize];
|
||||
fread(buf, sizeof(char), m_DataSize, fp);
|
||||
fclose(fp);
|
||||
|
||||
// Create buffer
|
||||
ALuint format = 0;
|
||||
if (m_BitsPerSample == 8) {
|
||||
if (m_Channels == 1) {
|
||||
format = AL_FORMAT_MONO8;
|
||||
} else if (m_Channels == 2) {
|
||||
format = AL_FORMAT_STEREO8;
|
||||
}
|
||||
}
|
||||
if (m_BitsPerSample == 16) {
|
||||
if (m_Channels == 1) {
|
||||
format = AL_FORMAT_MONO16;
|
||||
} else if (m_Channels == 2) {
|
||||
format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
}
|
||||
|
||||
ALuint buffer;
|
||||
alGenBuffers(1, &buffer);
|
||||
alBufferData(buffer, format, buf, m_DataSize, m_SampleRate);
|
||||
delete[] buf;
|
||||
|
||||
m_BufferCache[path] = buffer;
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
#ifndef SoundSystem_h__
|
||||
#define SoundSystem_h__
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "glm/common.hpp"
|
||||
#include "glm/gtx/rotate_vector.hpp" // Calculate Up vector
|
||||
#include "OpenAL/al.h"
|
||||
#include "OpenAL/alc.h"
|
||||
|
||||
#include "Core/World.h"
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/Transform.h" // Absolute transform
|
||||
#include "Sound/Sound.h"
|
||||
#include "Sound/EPlaySoundOnEntity.h"
|
||||
#include "Sound/EPlaySoundOnPosition.h"
|
||||
#include "Sound/EPlayBackgroundMusic.h"
|
||||
#include "Sound/EPauseSound.h"
|
||||
#include "Sound/EContinueSound.h"
|
||||
#include "Sound/EStopSound.h"
|
||||
#include "Sound/ESetBGMGain.h"
|
||||
#include "Sound/ESetSFXGain.h"
|
||||
|
||||
enum class SoundType {
|
||||
SFX,
|
||||
BGM
|
||||
};
|
||||
|
||||
struct Source
|
||||
{
|
||||
Source() { }
|
||||
Sound* SoundResource = nullptr;
|
||||
ALuint ALsource;
|
||||
SoundType Type;
|
||||
};
|
||||
|
||||
class SoundSystem
|
||||
{
|
||||
public:
|
||||
SoundSystem() { }
|
||||
SoundSystem(World* world, EventBroker* eventBroker, bool editorMode);
|
||||
~SoundSystem();
|
||||
// Update emitters / listener
|
||||
void Update(double dt);
|
||||
private:
|
||||
// Help functions for working with OpenaAL
|
||||
void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); };
|
||||
void setListenerVel(glm::vec3 vel) { alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); };
|
||||
void setListenerOri(glm::vec3 ori);
|
||||
glm::vec3 listnerPos() { glm::vec3 pos; alGetListener3f(AL_POSITION, &pos.x, &pos.y, &pos.z); return pos; };
|
||||
glm::vec3 listenerVel() { glm::vec3 vel; alGetListener3f(AL_VELOCITY, &vel.x, &vel.y, &vel.z); return vel; };
|
||||
glm::vec3 listenerOri() { glm::vec3 ori; alGetListener3f(AL_ORIENTATION, &ori.x, &ori.y, &ori.z); return ori; };
|
||||
void setSourcePos(ALuint source, glm::vec3 pos) { ALfloat spos[3] = { pos.x, pos.y, pos.z }; alSourcefv(source, AL_POSITION, spos); };
|
||||
void setSourceVel(ALuint source, glm::vec3 vel) { ALfloat svel[3] = { vel.x, vel.y, vel.z }; alSourcefv(source, AL_VELOCITY, svel); };
|
||||
|
||||
// Logic
|
||||
void initOpenAL();
|
||||
void updateEmitters(double dt);
|
||||
void updateListener(double dt);
|
||||
void deleteInactiveEmitters();
|
||||
void addNewEmitters(double dt);
|
||||
Source* createSource(std::string filePath);
|
||||
void playSound(Source* source);
|
||||
void stopSound(Source* source);
|
||||
void stopEmitters();
|
||||
ALenum getSourceState(ALuint source);
|
||||
void setGain(Source* source, float gain);
|
||||
void setSoundProperties(ALuint source, ComponentWrapper* soundComponent);
|
||||
|
||||
// OpenAL system variables
|
||||
ALCdevice* m_ALCdevice = nullptr;
|
||||
ALCcontext* m_ALCcontext = nullptr;
|
||||
|
||||
// Logic
|
||||
World* m_World = nullptr;
|
||||
EventBroker* m_EventBroker = nullptr;
|
||||
std::unordered_map<EntityID, Source*> m_Sources;
|
||||
float m_BGMVolumeChannel = 1.0f;
|
||||
float m_SFXVolumeChannel = 1.f;
|
||||
bool m_EditorEnabled = false;
|
||||
|
||||
// Events
|
||||
EventRelay<SoundSystem, Events::PlaySoundOnEntity> m_EPlaySoundOnEntity;
|
||||
bool OnPlaySoundOnEntity(const Events::PlaySoundOnEntity &e);
|
||||
EventRelay<SoundSystem, Events::PlaySoundOnPosition> m_EPlaySoundOnPosition;
|
||||
bool OnPlaySoundOnPosition(const Events::PlaySoundOnPosition &e);
|
||||
EventRelay<SoundSystem, Events::PlayBackgroundMusic> m_EPlayBackgroundMusic;
|
||||
bool OnPlayBackgroundMusic(const Events::PlayBackgroundMusic &e);
|
||||
EventRelay<SoundSystem, Events::PauseSound> m_EPauseSound;
|
||||
bool OnPauseSound(const Events::PauseSound &e);
|
||||
EventRelay<SoundSystem, Events::StopSound> m_EStopSound;
|
||||
bool OnStopSound(const Events::StopSound &e);
|
||||
EventRelay<SoundSystem, Events::ContinueSound> m_EContinueSound;
|
||||
bool OnContinueSound(const Events::ContinueSound &e);
|
||||
EventRelay<SoundSystem, Events::SetBGMGain> m_ESetBGMGain;
|
||||
bool OnSetBGMGain(const Events::SetBGMGain &e); // Not tested
|
||||
EventRelay<SoundSystem, Events::SetSFXGain> m_ESetSFXGain;
|
||||
bool OnSetSFXGain(const Events::SetSFXGain &e); // Not tested
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user