Compare commits

..

68 Commits

Author SHA1 Message Date
William Moberg a346a329b3 Added an option to disable the Pool allocation in Config.ini, in case there is a mess with the MemoryPool. 2016-01-18 10:16:35 +01:00
stiffly d28583ca9e Fixes for #34 (Licenses) 2016-01-15 17:20:11 +01:00
Jace 7b2a21f0b0 Merge pull request #34 from teamfisk/Sound
Sound
2016-01-15 16:26:55 +01:00
stiffly 5c45dbdd10 Merge remote-tracking branch 'origin/master' into Sound
# Conflicts:
#	resources/Schema/Types/Entity.xsd
2016-01-15 16:25:32 +01:00
Jace ce8dcd3022 Merge pull request #33 from teamfisk/Forward+
Forward+
2016-01-15 16:20:53 +01:00
Jace a2e19013c6 Merge pull request #32 from teamfisk/AsyncResourceLoad
Async resource load
2016-01-15 16:20:36 +01:00
William Moberg c09fe4ae55 Added a bool option to disable threads in in the configfile regarding resource loading. 2016-01-15 16:18:39 +01:00
stiffly be33dfbd69 Forgot to change the velocity for the emitters as well... 2016-01-15 16:10:02 +01:00
stiffly 63704b2e6b Now calculating the velocity for the listener correctly. 2016-01-15 15:43:20 +01:00
Tleety 3de853ac8b Frustum culling now works correctly for all resolutions 2016-01-15 15:38:14 +01:00
William Moberg f5ea4d513c ResourceManager::Load never returns null, throws exceptions instead. 2016-01-15 15:25:01 +01:00
stiffly d9dd7f535f When changing camera listener is updated. Also fixed some crashes in RenderSystem when there were no cameras available. 2016-01-15 13:45:08 +01:00
William Moberg 76f90ab031 The main thread is not mutex blocked while child threads load anymore. 2016-01-15 11:29:46 +01:00
stiffly 3e2cb33bc0 Played around with new map MapVersion1. Was fun ヽ(´▽`)/ 2016-01-15 11:23:29 +01:00
Tleety 14bc850fab Merge remote-tracking branch 'origin/master' into Forward+ 2016-01-15 11:02:27 +01:00
Tleety ecf524eb4e Merge remote-tracking branch 'origin/master' into Forward+
# Conflicts:
#	include/Engine/Rendering/PickingPass.h
#	include/Engine/Rendering/Renderer.h
#	resources/Schema/Entities/Test.xml
#	src/Engine/Rendering/DrawScenePass.cpp
#	src/Engine/Rendering/PickingPass.cpp
#	src/Engine/Rendering/RenderQueueFactory.cpp
#	src/Engine/Rendering/Renderer.cpp
2016-01-15 11:01:58 +01:00
William Moberg 4cf6dcfc14 Merge branch 'master' into AsyncResourceLoad
# Conflicts:
#	include/Engine/Rendering/RawModel.h
#	src/Engine/Rendering/RenderQueueFactory.cpp
2016-01-15 10:10:57 +01:00
stiffly 32634f742e Merge remote-tracking branch 'origin/master' into Sound 2016-01-15 09:53:39 +01:00
stiffly e248b37ea8 Merge remote-tracking branch 'origin/master' into Sound
# Conflicts:
#	src/Game/Game.cpp
2016-01-15 09:52:52 +01:00
Jace 627108c6ee Fixes for #30
# Conflicts:
#	src/Game/Game.cpp
2016-01-14 18:15:38 +01:00
Viktor Ljung a8f7d5f6b9 Merge pull request #30 from teamfisk/Rendering
Rendering Scenes
2016-01-14 16:43:35 +01:00
William Moberg 71047b08ec Async load works, using exceptions for special resources. 2016-01-14 16:27:45 +01:00
viktorljung c99a8685bb Removed Debug scene 2016-01-14 15:40:13 +01:00
stiffly b80ecc29d8 Added comments and cleaned up in Game.cpp/h 2016-01-14 15:32:53 +01:00
viktorljung 143648860b Added world pointer to PickData 2016-01-14 15:32:41 +01:00
viktorljung 96371a08c8 Changed Picking colors from vec2 to ivec2. Picking now working for multiple scenes (Solution not perfect in the editor, yet) 2016-01-14 15:26:06 +01:00
stiffly c916185a7c Does not crash when removing soundemitter component. 2016-01-14 15:06:26 +01:00
stiffly 7f0ff6c4d7 Added a sound testing level. 2016-01-14 14:20:34 +01:00
stiffly 773a417a90 Merge branch 'master' into Sound 2016-01-14 14:19:48 +01:00
stiffly cca64dca24 Refactoring and commenting. 2016-01-14 13:54:38 +01:00
viktorljung e7f02f14a0 Added Transform.h that holds all the AbsoluteTransformation functions. Camera now working better with scenes. Changed Modeljob Matrix to only hold the model matrix instad of all matrix info 2016-01-14 11:12:02 +01:00
William Moberg 9f185a1e35 Wrecked the last commit. Async loading works now. 2016-01-13 18:51:45 +01:00
William Moberg a143ae7c85 Changed to relative #include paths. 2016-01-13 15:53:55 +01:00
William Moberg a58cc33ed0 WIP, multithreaded loading based on exceptions, very slow probably. 2016-01-13 10:58:31 +01:00
William Moberg 704e8825c4 Merge pull request #29 from teamfisk/Networking
Networking
2016-01-12 17:48:33 +01:00
Jocke 2284399538 Removed Close method from Client, Server and Network.
Removed legacy variable m_ThreadIsRunning in Client.h and Server.h.
Removed m_EventBroker->Unsubscribe(m_EInputCommand) in Client destructor.
2016-01-12 17:47:03 +01:00
viktorljung 0f17f9a888 Merge remote-tracking branch 'origin/master' into Rendering
# Conflicts:
#	include/Engine/Editor/EditorSystem.h
#	include/Engine/Rendering/EPicking.h
#	include/Engine/Rendering/Renderer.h
#	include/Game/Game.h
#	resources/Schema/Components.xsd
#	resources/Schema/Entities/Test.xml
#	src/Engine/Editor/EditorSystem.cpp
#	src/Engine/Rendering/RawModel.cpp
#	src/Engine/Rendering/RenderQueueFactory.cpp
#	src/Engine/Rendering/Renderer.cpp
#	src/Game/Game.cpp
2016-01-12 16:13:20 +01:00
stiffly c9f11f62d2 Does not delete emitters that are paused and has not yet been played. 2016-01-12 15:37:10 +01:00
stiffly 5697e8bc85 Deleting an entity now tells openal to behave accordingly. 2016-01-12 14:51:10 +01:00
stiffly 729ebe6c8b Merge remote-tracking branch 'origin/master' into Sound
# Conflicts:
#	README.md
#	resources/Schema/Components.xsd
#	resources/Schema/Types/Entity.xsd
2016-01-12 14:50:10 +01:00
Jocke 56ac592d6d Removed debug code from Game.cpp 2016-01-12 14:16:01 +01:00
stiffly 976033c2f6 Added events: PlayBackgroundMusic, SetBGMGain, SetSFXGain. Added some editor specific code. 2016-01-12 14:03:00 +01:00
Jocke 2bf1d53f2c Merge remote-tracking branch 'origin/master' into Networking 2016-01-12 13:17:00 +01:00
Jocke 236230d12c Packets now dynamically allocates more memory when they need it.
Increased local receive buffer for Client and Server() and removed the magic number that was used
In Server.h and Client.h
(char readBuffer[INPUTSIZE] = { 0 }).
Packets start size has now been increased to 512 bytes.
Changed ComponentInfo::FieldsInOrder to store strings instead of pointers.
Removed HasEntity() and are now using ValidEntity() instead.
2016-01-12 12:00:19 +01:00
viktorljung 2450769190 some cleanup 2016-01-12 11:51:47 +01:00
viktorljung d469fe6e9a Removed picking event and added a pick function to renderer 2016-01-12 11:45:50 +01:00
Tleety 24ba3ae1f6 WIP, falloff things.
# Conflicts:
#	resources/Schema/Components/PointLight.xsd
#	resources/Shaders/ForwardPlus.frag.glsl
2016-01-11 17:57:15 +01:00
Tleety fa6dd2dc67 Basic transparancy working. 2016-01-11 17:57:15 +01:00
Tleety 3c5966d174 Now sort models according to depth. 2016-01-11 17:57:15 +01:00
Tleety 0cf8d26557 Revert "Revert "Forward+""
This reverts commit b908a9f9c6.
2016-01-11 17:56:58 +01:00
stiffly f80ad1377b Making use of Doppler effect. Added a bunch of events: Pause, stop, continue, variations of play. 2016-01-11 17:52:27 +01:00
viktorljung 3feee7fd35 Changed the structure of how RenderJobs are handled 2016-01-11 17:01:17 +01:00
Jocke b37ffc7449 WIP Model component not working. 2016-01-11 14:58:49 +01:00
Jocke 6c13916eec Removed unnecessary code. 2016-01-11 14:58:30 +01:00
stiffly f0ad28bac4 Removed some comments. Basically did nothing 2016-01-11 14:58:15 +01:00
viktorljung b8db80bc40 Added camera to PickingPass and fixed memory leak 2016-01-11 10:47:39 +01:00
viktorljung a7b43b06a2 Camera component and RenderQueue changes 2016-01-08 16:21:59 +01:00
stiffly 3cce9f8075 Using absolute transform 2016-01-08 15:29:20 +01:00
stiffly da6e50dc7e Correct orientation. Need to clean this up. 2016-01-07 17:04:43 +01:00
stiffly 2838446072 In lack of camera entity I created a Listener cube to test 3D sound. Works fine. Updates listener pos each tick. 2016-01-07 16:03:33 +01:00
stiffly d8c4c6e5ff Created a primitive SoundSystem. Can play a sound with 'P' button. Using resourcemanager. Not using the created components yet. 2016-01-07 15:22:46 +01:00
viktorljung bd82f75dd0 Some merge fixes, needs more work 2015-12-18 15:28:44 +01:00
viktorljung aeca1dec18 Merge remote-tracking branch 'origin/master' into Rendering
# Conflicts:
#	src/Engine/Editor/EditorSystem.cpp
#	src/Engine/Rendering/PickingPass.cpp
#	src/Game/Game.cpp
2015-12-17 11:17:58 +01:00
viktorljung 0f1b06f74e Fixed camera rotation bug 2015-12-17 11:13:34 +01:00
viktorljung fa66e9ff47 Camera Switch event now working, Camera models Rotation still bugged 2015-12-15 15:29:19 +01:00
viktorljung d9ea0192d1 Added RenderSystem and removed RenderQueueFactory 2015-12-14 20:07:02 +01:00
viktorljung ef07a9d536 Merge remote-tracking branch 'origin/master' into Rendering
# Conflicts:
#	include/Engine/Rendering/RenderQueueFactory.h
2015-12-14 19:11:00 +01:00
viktorljung 05b78265be Fixed some transparency bugs and started on component based camera 2015-12-14 19:10:00 +01:00
116 changed files with 3765 additions and 1447 deletions
+2 -1
View File
@@ -11,7 +11,8 @@ Libraries bundled along with binaries for Windows (MSVC14), available as a submo
| **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) |
| **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) |
| **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) |
| **[nativefiledialog](https://github.com/mlabbe/nativefiledialog) | 2016-01-08 | https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE |
| **[nativefiledialog](https://github.com/mlabbe/nativefiledialog)** | 2016-01-08 | [nativefiledialog Licence](https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE) |
| **[OpenAL](https://www.openal.org/)** | 1.1 | [OpenAL License](resources/Licenses/OpenAL.txt)
#### External libraries
Libraries that are too big to be bundled with the project.
+1 -1
Submodule assets updated: c8e631f449...a3c92ac876
+4 -4
View File
@@ -7,10 +7,10 @@
#include <vector>
#include "Core/Ray.h"
#include "Core/AABB.h"
#include "Engine/Rendering/RawModel.h"
#include "Core/Entity.h"
#include "../Core/Ray.h"
#include "../Core/AABB.h"
#include "../Rendering/RawModel.h"
#include "../Core/Entity.h"
class World;
struct ComponentWrapper;
+4 -4
View File
@@ -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
{
+2 -2
View File
@@ -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;
+2 -1
View File
@@ -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;
};
+18 -28
View File
@@ -69,7 +69,6 @@ public:
{
Unknown,
Entity,
EntityRef,
Component,
ComponentField
};
@@ -78,32 +77,29 @@ public:
: m_Handler(handler)
, m_Reader(reader)
{
// Push first parent
m_EntityStack.push(EntityID_Invalid);
// 0 is imaginary world entity
m_EntityStack.push(0);
m_StateStack.push(State::Unknown);
}
void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override
{
std::string name = XS::ToString(_localName);
if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity || m_StateStack.top() == State::EntityRef) {
if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) {
if (name == "Entity") {
// Handle entity references
const XMLCh* refAttr = attrs.getValue(XS::ToXMLCh("ref"));
std::string ref = XS::ToString(refAttr);
if (ref.empty()) {
m_StateStack.push(State::Entity);
onStartEntity(attrs);
} else {
m_StateStack.push(State::EntityRef);
onStartEntityRef(ref, attrs);
}
m_StateStack.push(State::Entity);
onStartEntity(attrs);
return;
}
if (name == "EntityRef") {
onStartEntityRef(attrs);
return;
}
}
std::string uri = XS::ToString(_uri);
if (m_StateStack.top() == State::Entity || m_StateStack.top() == State::EntityRef) {
if (m_StateStack.top() == State::Entity) {
if (uri == "components") {
m_StateStack.push(State::Component);
onStartComponent(name);
@@ -129,16 +125,10 @@ public:
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override
{
std::string name = XS::ToString(_localName);
if (m_StateStack.top() == State::Entity || m_StateStack.top() == State::EntityRef) {
if (m_StateStack.top() == State::Entity) {
if (name == "Entity") {
if (m_StateStack.top() == State::Entity) {
m_StateStack.pop();
if (m_StateStack.top() == State::EntityRef) {
onEndEntityRef();
} else {
onEndEntity();
}
}
m_StateStack.pop();
onEndEntity();
return;
}
}
@@ -198,16 +188,16 @@ private:
{
m_EntityStack.pop();
}
void onStartEntityRef(const std::string& ref, const xercesc::Attributes& attrs)
void onStartEntityRef(const xercesc::Attributes& attrs)
{
std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file")));
xercesc::SAX2XMLReader* parser = xercesc::XMLReaderFactory::createXMLReader();
parser->setContentHandler(this);
parser->setErrorHandler(this);
parser->parse(ref.c_str());
parser->parse(path.c_str());
delete parser;
//m_StateStack.push(State::Entity);
}
void onEndEntityRef() { }
void onStartComponent(const std::string& name)
{
//LOG_DEBUG(" Component: %s", name.c_str());
+1 -1
View File
@@ -9,7 +9,7 @@ class EntityFileParser
public:
EntityFileParser(const EntityFile* entityFile);
void MergeEntities(World* world, EntityID parent = EntityID_Invalid);
void MergeEntities(World* world);
private:
const EntityFile* m_EntityFile;
+14 -4
View File
@@ -5,6 +5,14 @@
template <typename T>
class MemoryPoolForwardIterator;
namespace DisableMemoryPool
{
//if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
//if false -> Use pool allocation.
//Should default to false, unless the DisableMemoryPool is true in the Config.ini files.
extern bool Value;
}
//This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride).
//Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot
//will the size of the object type) you should use ObjectPool<T> instead, your life will become easier.
@@ -80,8 +88,8 @@ public:
//If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool".
char* Allocate()
{
for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot]; ++m_CurrentAllocSlot);
if (m_CurrentAllocSlot < m_NumSlots) {
for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot] && !DisableMemoryPool::Value; ++m_CurrentAllocSlot);
if (m_CurrentAllocSlot < m_NumSlots && !DisableMemoryPool::Value) {
if (m_LowestAllocatedSlot > m_CurrentAllocSlot)
m_LowestAllocatedSlot = m_CurrentAllocSlot;
//Mark the slot as allocated.
@@ -93,7 +101,9 @@ public:
else {
m_ExtraMemory.push_back((char*)malloc(m_Stride));
//We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead.
LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
if (!DisableMemoryPool::Value) {
LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
}
return m_ExtraMemory.back();
}
}
@@ -108,7 +118,7 @@ public:
//(i.e. IsAllocatedInPool may give false positives)
//if it was malloc():ed
//so, we may enter here even if we shouldn't.
if (IsAllocatedInPool(obj)) {
if (!DisableMemoryPool::Value && IsAllocatedInPool(obj)) {
--m_NumAllocatedSlots;
const size_t freeSlot = (obj - m_StartAddress) / m_Stride;
m_SlotIsAllocated[freeSlot] = false;
+1 -1
View File
@@ -2,7 +2,7 @@
#define Ray_h__
#include "../GLM.h"
#include "Common.h"
#include "../Common.h"
class Ray
{
+132 -39
View File
@@ -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
+17
View File
@@ -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
+5 -6
View File
@@ -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,12 +25,12 @@ public:
private:
IRenderer* m_Renderer;
World* m_World = nullptr;
Camera* m_Camera = nullptr;
bool m_Enabled;
bool m_Visible;
boost::filesystem::path m_DefaultEntityDir;
boost::filesystem::path m_CurrentFile;
std::map<boost::filesystem::path, EntityID> m_CurrentFiles;
std::vector<glm::vec2> m_PickingQueue;
enum class WidgetMode
@@ -58,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;
@@ -76,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);
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+3 -4
View File
@@ -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();
+1 -1
View File
@@ -6,7 +6,7 @@
#include "Network/Packet.h"
#define MAXCONNECTIONS 8
#define INPUTSIZE 128
#define INPUTSIZE 4097
class Network
{
+9 -4
View File
@@ -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
+1 -6
View File
@@ -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);
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../Core/ResourceManager.h"
class BaseTexture : public Resource
class BaseTexture : public ThreadUnsafeResource
{
friend class ResourceManager;
+6 -8
View File
@@ -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; }
+38
View File
@@ -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
+7 -1
View File
@@ -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
+1 -1
View File
@@ -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
-74
View File
@@ -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
+23
View File
@@ -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
+26 -13
View File
@@ -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
+5 -1
View File
@@ -4,7 +4,7 @@
#include "RawModel.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;
+55
View File
@@ -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
+23 -6
View File
@@ -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
+39
View File
@@ -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
+5 -1
View File
@@ -46,14 +46,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;
+32
View File
@@ -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
+47 -103
View File
@@ -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
+55
View File
@@ -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
+14 -69
View File
@@ -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
+17
View File
@@ -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
+17
View File
@@ -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
+21
View File
@@ -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
+16
View File
@@ -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
+16
View File
@@ -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
+17
View File
@@ -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
+113
View File
@@ -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
+101
View File
@@ -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
+9 -4
View File
@@ -8,7 +8,6 @@
#include "Core/InputManager.h"
#include "GUI/Frame.h"
#include "Core/World.h"
#include "Rendering/RenderQueueFactory.h"
#include "Input/InputProxy.h"
#include "Input/KeyboardInputHandler.h"
#include "Input/MouseInputHandler.h"
@@ -19,6 +18,7 @@
#include "PlayerSystem.h"
#include "Editor/EditorSystem.h"
#include "Core/EntityFile.h"
#include "Rendering/RenderSystem.h"
#include "Core/EntityFileParser.h"
// Network
@@ -27,6 +27,8 @@
#include "Network/Server.h"
#include "Network/Client.h"
// Sound
#include "Sound/SoundSystem.h"
class Game
{
@@ -47,7 +49,7 @@ private:
GUI::Frame* m_FrameStack;
World* m_World;
SystemPipeline* m_SystemPipeline;
RenderQueueFactory* m_RenderQueueFactory;
RenderFrame* m_RenderFrame;
// Network variables
boost::thread m_NetworkThread;
@@ -56,8 +58,11 @@ private:
Network* m_ClientOrServer;
bool m_IsClientOrServer = false;
EventRelay<Game, Events::InputCommand> m_EInputCommand;
bool debugOnInputCommand(const Events::InputCommand& e);
// Sound
SoundSystem* m_SoundSystem;
//EventRelay<Game, Events::InputCommand> m_EInputCommand;
//bool debugOnInputCommand(const Events::InputCommand& e);
void debugInitialize();
void debugTick(double dt);
+7 -2
View File
@@ -2,7 +2,9 @@
LogLevel=1
LoadMap=
EditorEnabled=false
; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
; if false -> Use pool allocation.
DisableMemoryPool=false
[Video]
Fullscreen=false
@@ -16,4 +18,7 @@ StartNetwork=false
IsServer=false
Name=Bob
Address=127.0.0.1
Port=13
Port=13
[Multithreading]
ResourceLoading=true
+510
View File
@@ -0,0 +1,510 @@
This file is part of the OpenAL software.
The licenses which components of this software fall under are as follows.
All components are under a LGPL license.
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+4
View File
@@ -6,7 +6,11 @@
<xs:include schemaLocation="Components/Test.xsd"/>
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
<xs:include schemaLocation="Components/Player.xsd"/>
<xs:include schemaLocation="Components/Camera.xsd"/>
<xs:include schemaLocation="Components/AABB.xsd"/>
<xs:include schemaLocation="Components/PointLight.xsd"/>
<xs:include schemaLocation="Components/Trigger.xsd"/>
<xs:include schemaLocation="Components/Health.xsd"/>
<xs:include schemaLocation="Components/Listener.xsd"/>
<xs:include schemaLocation="Components/SoundEmitter.xsd"/>
</xs:schema>
+6
View File
@@ -0,0 +1,6 @@
<c:Camera>
<Name>cam</Name>
<FOV>60.0</FOV>
<NearClip>0.01</NearClip>
<FarClip>5000</FarClip>
</c:Camera>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Camera">
<xs:annotation>
<xs:documentation>It's a camera thingy!</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Name" type="t:string" minOccurs="0"/>
<xs:element name="FOV" type="t:double" minOccurs="0"/>
<xs:element name="NearClip" type="t:double" minOccurs="0"/>
<xs:element name="FarClip" type="t:double" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+3
View File
@@ -0,0 +1,3 @@
<c:Listener>
</c:Listener>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Listener">
</xs:element>
</xs:schema>
@@ -0,0 +1,7 @@
<c:PointLight>
<Color R="1" G="1" B="1" A="1"/>
<Radius>1.0</Radius>
<Intensity>0.8</Intensity>
<Falloff>0.3</Falloff>
<Visible>true</Visible>
</c:PointLight>
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="PointLight">
<xs:annotation>
<xs:documentation>A pointlight that lights up geometry in a radius.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Color" type="t:Color" minOccurs="0"/>
<xs:element name="Radius" type="t:double" minOccurs="0"/>
<xs:element name="Intensity" type="t:double" minOccurs="0"/>
<xs:element name="Falloff" type="t:double" minOccurs="0" minInclusive="0" maxInclusive="1"/>
<xs:element name="Visible" type="t:bool" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,9 @@
<c:SoundEmitter>
<FilePath></FilePath>
<Gain>1.0</Gain>
<Pitch>1.0</Pitch>
<Loop>false</Loop>
<MaxDistance>20.0</MaxDistance>
<RollOffFactor>1.0</RollOffFactor>
<ReferenceDistance>1.0</ReferenceDistance>
</c:SoundEmitter>
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="SoundEmitter">
<xs:complexType>
<xs:all>
<xs:element name="FilePath" type="t:string" minOccurs="0"/>
<xs:element name="Gain" type="t:double" minOccurs="0"/>
<xs:annotation><xs:documentation>The "volume" of the emitter. A value betweeen 0-1</xs:documentation></xs:annotation>
<xs:element name="Pitch" type="t:double" minOccurs="0"/>
<xs:annotation><xs:documentation>The pitch of the emitter. A value betweeen 0-1</xs:documentation></xs:annotation>
<xs:element name="Loop" type="t:bool" minOccurs="0"/>
<xs:annotation><xs:documentation>If the sound should loop or not.</xs:documentation></xs:annotation>
<xs:element name="MaxDistance" type="t:double" minOccurs="0"/>
<xs:annotation><xs:documentation>The distance where there will no longer be any attenuation.</xs:documentation></xs:annotation>
<xs:element name="RollOffFactor" type="t:double" minOccurs="0"/>
<xs:annotation><xs:documentation>The rolloff rate of the source.</xs:documentation></xs:annotation>
<xs:element name="ReferenceDistance" type="t:double" minOccurs="0"/>
<xs:annotation><xs:documentation>The distance that the source will be the loudest.</xs:documentation></xs:annotation>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -17,7 +17,7 @@
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<c:Model>
<Resource>Models/ScaleWidget.obj</Resource>
<Resource>Models/Core/UnitSphere.obj</Resource>
</c:Model>
</Components>
</Entity>
+56 -48
View File
@@ -1,49 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
<Components>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Scale X="100" Y="1" Z="100"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitPlane.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="1" Y="1" Z="0"/>
<Orientation X="0" Y="0.78539" Z="0"/>
</c:Transform>
<c:Model>
<Resource>An error</Resource>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="2" Y="0" Z="0"/>
<Orientation X="0" Y="0.78539" Z="0"/>
</c:Transform>
<c:Model>
<Resource>An error</Resource>
</c:Model>
</Components>
<Children>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
</c:Model>
<c:Transform>
<Scale X="100" Y="1" Z="100"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Model>
<Resource>An error</Resource>
</c:Model>
<c:Transform>
<Position X="1" Y="1" Z="0"/>
<Orientation X="0" Y="0.785390019" Z="0"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>An error</Resource>
</c:Model>
<c:Transform>
<Position X="2" Y="0" Z="0"/>
<Orientation X="0" Y="0.785390019" Z="0"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
<Entity>
<Components>
<c:Camera/>
<c:Transform>
<Position X="5.85247707" Y="3.8454349" Z="-1.14486957"/>
<Orientation X="2.51327395" Y="1.23916209" Z="-3.1415925"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity ref="Schema/Entities/RaptorCopter.xml">
<Components>
<c:Transform>
<Position X="1" Y="2" Z="3" />
</c:Transform>
</Components>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
<Components>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="1" Z="10"/>
</c:Transform>
<c:Model>
<Resource>Models/Camera.obj</Resource>
</c:Model>
<c:Camera>
<Name>MainCamera</Name>
</c:Camera>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="5" Y="1" Z="5"/>
</c:Transform>
<c:Model>
<Resource>Models/Camera.obj</Resource>
</c:Model>
<c:Camera>
<Name>ActionCamera</Name>
</c:Camera>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="-1" Z="0"/>
<Scale X="100" Y="1" Z="100"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitPlane.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
</c:Transform>
<c:Model>
<Resource>An error</Resource>
</c:Model>
</Components>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:SoundEmitter>
<FilePath></FilePath>
</c:SoundEmitter>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.58431375" R="0.43921569"/>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Camera/>
<c:Listener/>
<c:Transform>
<Position X="-1.81944144" Y="1.960464" Z="8.79182625"/>
<Orientation X="-0.261799812" Y="-0.261786997" Z="-8.48482742e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+6 -101
View File
@@ -9,114 +9,19 @@
<Resource>Models/DummyScene.obj</Resource>
</c:Model>
</Components>
</Entity>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="-1.5"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<c:Model>
<Resource>Models/ScaleWidget.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="1.5"/>
<Scale X="2" Y="2" Z="2"/>
</c:Transform>
<c:Model>
<Resource>Models/RotationWidget.obj</Resource>
</c:Model>
<c:Trigger>
</c:Trigger>
</Components>
</Entity>
<!--<Entity>
<Components>
<c:Player>
<Velocity X="0" Y="0" Z="0"/>
</c:Player>
<c:Transform>
<Position X="2.5"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
</c:Model>
<c:AABB>
</c:AABB>
</Components>
</Entity>-->
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="-0"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<!--<c:Move>
<Speed>1</Speed>
<Direction X="-1"/>
<Rotation Y="3.14"/>
</c:Move>-->
<c:Camera>
</c:Camera>
<c:Model>
<Resource>Models/Camera.obj</Resource>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Orientation X="0.0" Y="0" Z="1.0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitRaptor.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="-0.01" Y="0.55"/>
<Orientation X="0" Y="0" Z="-1"/>
</c:Transform>
<c:RaptorCopter>
<Speed>20</Speed>
<Axis Y="1"/>
</c:RaptorCopter>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="1.57" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Camera/>
<c:Transform>
<Position X="-8.58846378" Y="9.3929615" Z="14.3944101"/>
<Orientation X="-0.645772398" Y="-0.314115167" Z="-4.700399e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Model>
<Resource></Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+10 -1
View File
@@ -16,6 +16,9 @@
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
<xs:element ref="c:Player" minOccurs="0"/>
<xs:element ref="c:Health" minOccurs="0"/>
<xs:element ref="c:PointLight" minOccurs="0"/>
<xs:element ref="c:Listener" minOccurs="0"/>
<xs:element ref="c:SoundEmitter" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
@@ -24,13 +27,19 @@
<xs:complexType>
<xs:sequence>
<xs:element ref="Entity" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="EntityRef" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:attribute name="file" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute ref="xml:base"/>
<xs:attribute name="name" type="xs:string" minOccurs="0" default=""/>
<xs:attribute name="ref" type="xs:string" minOccurs="0" default=""/>
</xs:complexType>
</xs:element>
</xs:schema>
View File
-3
View File
@@ -1,8 +1,5 @@
#version 430
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform vec4 Color;
uniform sampler2D texture0;
+1 -1
View File
@@ -25,7 +25,7 @@ out VertexData{
void main()
{
gl_Position = P*V*M * vec4(Position, 1.0);
gl_Position = P * V * M * vec4(Position, 1.0);
Output.Position = Position;
Output.TextureCoordinate = TextureCoords;
+154
View File
@@ -0,0 +1,154 @@
#version 430
//in uvec3 gl_NumWorkGroups; //contains the number of workgroups that have been dispatched to a compute shader
//in uvec3 gl_WorkGroupID; //contains the index of the workgroup currently being operated on by a compute shader
//in uvec3 gl_LocalInvocationID; //contains the index of work item currently being operated on by a compute shader
//in uvec3 gl_GlobalInvocationID; //contains the global index of work item currently being operated on by a compute shader
//in uint gl_LocalInvocationIndex; //contains the local linear index of work item currently being operated on by a compute shader
#define MAX_LIGHTS_PER_TILE 200
#define TILE_SIZE 16
uniform mat4 V;
uniform vec2 ScreenDimensions;
struct Plane {
vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
layout (std430, binding = 0) buffer FrustumBuffer
{
Frustum Data[];
} Frustums;
struct PointLight {
vec4 Position;
vec4 Color;
float Radius;
float Intensity;
float Falloff;
float Padding;
};
layout (std430, binding = 1) buffer LightBuffer
{
PointLight List[];
} PointLights;
struct LightGrid {
float Start;
float Amount;
vec2 Padding;
};
layout (std430, binding = 2) buffer LightGridBuffer
{
LightGrid Data[];
} LightGrids;
layout (std430, binding = 3) buffer LightOffsetBuffer
{
int LightOffset[];
};
layout (std430, binding = 4) buffer LightIndexBuffer
{
float LightIndex[];
};
shared int GroupLightCount;
shared int GroupLightIndexStartOffset;
shared int GroupLightIndex[MAX_LIGHTS_PER_TILE];
shared Frustum GroupFrustum;
int GroupIndex;
bool SphereInsidePlane(vec3 center, float radius, Plane plane)
{
return dot(plane.Normal, center) - plane.d > -radius;
}
bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zNear, float zFar*/)
{
//Check depth here
//if ( sphere.c.z - sphere.r > zNear || sphere.c.z + sphere.r < zFar )
//{
// result = false;
//}
for (int i =0; i < 4; i++)
{
if(! SphereInsidePlane(center, radius, frustum.Planes[i]))
{
return false;
}
}
return true;
}
void AppendLight(int li)
{
int index;
index = atomicAdd(GroupLightCount, 1);
if( index < MAX_LIGHTS_PER_TILE )
{
GroupLightIndex[index] = int(li);
}
}
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main ()
{
GroupIndex = int(gl_WorkGroupID.x + (gl_WorkGroupID.y * int(ScreenDimensions.x/TILE_SIZE)));
if(gl_LocalInvocationIndex == 0)
{
GroupLightCount = 0;
GroupFrustum = Frustums.Data[GroupIndex];
}
barrier();
memoryBarrierShared();
for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE)
{
PointLight light = PointLights.List[i];
//if pointlight
//Pos i view antagligen
if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum))
{
//TODO: Fix transparent and opaque list, and depth test.
AppendLight( i );
}
//if conelight
//if directional
}
barrier();
memoryBarrierShared();
if(gl_LocalInvocationIndex == 0)
{
GroupLightIndexStartOffset = atomicAdd(LightOffset[0], GroupLightCount);
LightGrids.Data[GroupIndex].Start = GroupLightIndexStartOffset;
LightGrids.Data[GroupIndex].Amount = GroupLightCount;
}
barrier();
for (uint i = gl_LocalInvocationIndex; i < GroupLightCount; i += TILE_SIZE * TILE_SIZE )
{
LightIndex[GroupLightIndexStartOffset + i] = GroupLightIndex[i];
}
}
+132
View File
@@ -0,0 +1,132 @@
#version 430
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform vec4 Color;
uniform vec2 ScreenDimensions;
uniform sampler2D texture0;
#define TILE_SIZE 16
struct PointLight {
vec4 Position;
vec4 Color;
float Radius;
float Intensity;
float Falloff;
float Padding;
};
layout (std430, binding = 1) buffer LightBuffer
{
PointLight List[];
} PointLights;
struct LightGrid {
float Start;
float Amount;
vec2 Padding;
};
layout (std430, binding = 2) buffer LightGridBuffer
{
LightGrid Data[];
} LightGrids;
layout (std430, binding = 4) buffer LightIndexBuffer
{
float LightIndex[];
};
in VertexData{
vec3 Position;
vec3 Normal;
vec2 TextureCoordinate;
vec4 DiffuseColor;
}Input;
out vec4 fragmentColor;
vec4 scene_ambient = vec4(0.3,0.3,0.3,1);
struct LightResult {
vec4 Diffuse;
vec4 Specular;
};
float CalcAttenuation(float radius, float dist, float falloff) {
return 1.0 - smoothstep(radius * 0.3, radius, dist);
}
vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) {
vec4 R = normalize( reflect(-lightVec, normal));
float RdotV = max( dot(R, viewVec), 0.0);
return lightColor * pow(RdotV, 90.0);
}
vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) {
float power = max( dot(normal, lightVec), 0.0);
return lightColor * power;
}
LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff)
{
vec4 L = lightPos - position;
float dist = length(L);
L = normalize(L);
float attenuation = CalcAttenuation(lightRadius, dist, falloff);
LightResult result;
result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity;
result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity;
return result;
}
void main()
{
vec4 texel = texture2D(texture0, Input.TextureCoordinate);
vec4 position = V * M * vec4(Input.Position, 1.0);
vec4 normal = V * vec4(Input.Normal, 0.0);
vec4 viewVec = normalize(-position);
vec2 tilePos;
tilePos.x = int(gl_FragCoord.x/16);
tilePos.y = int(gl_FragCoord.y/16);
LightResult totalLighting;
totalLighting.Diffuse = scene_ambient;
int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE)));
int start = int(LightGrids.Data[currentTile].Start);
int amount = int(LightGrids.Data[currentTile].Amount);
//for(int i = 0; i < 3; i++)
for(int i = start; i < start + amount; i++)
{
int l = int(LightIndex[i]);
LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal, PointLights.List[i].Falloff);
totalLighting.Diffuse += result.Diffuse;
totalLighting.Specular += result.Specular;
}
fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color;
//fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse) * texel * Color;
//fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1);
//fragmentColor = texel * Input.DiffuseColor * Color;
if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 )
{
//fragmentColor += vec4(0.5, 0, 0, 0);
} else {
//fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1);
}
}
+34
View File
@@ -0,0 +1,34 @@
#version 430
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec3 Tangent;
layout(location = 3) in vec3 BiTangent;
layout(location = 4) in vec2 TextureCoords;
layout(location = 5) in vec4 DiffuseVertexColor;
layout(location = 6) in vec4 SpecularVertexColor;
layout(location = 7) in vec4 BoneIndices1;
layout(location = 8) in vec4 BoneIndices2;
layout(location = 9) in vec4 BoneWeights1;
layout(location = 10) in vec4 BoneWeights2;
out VertexData{
vec3 Position;
vec3 Normal;
vec2 TextureCoordinate;
vec4 DiffuseColor;
}Output;
void main()
{
gl_Position = P*V*M * vec4(Position, 1.0);
Output.Position = Position;
Output.TextureCoordinate = TextureCoords;
Output.Normal = Normal;
Output.DiffuseColor = DiffuseVertexColor;
}
+27 -25
View File
@@ -1,7 +1,6 @@
#version 430
#define TILE_SIZE 16
#define NUM_TILES 3600
uniform mat4 P;
uniform vec2 ScreenDimensions;
@@ -16,7 +15,7 @@ struct Frustum {
layout (std430, binding = 0) buffer FrustumBuffer
{
Frustum Data[3600];
Frustum Data[];
} Frustums;
vec4 ConvertToView(vec4 ScreenCoords)
@@ -43,31 +42,34 @@ Plane ComputePlane( vec3 p0, vec3 p1, vec3 p2 )
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main ()
{
if(gl_GlobalInvocationID.x * TILE_SIZE < ScreenDimensions.x && gl_GlobalInvocationID.y * TILE_SIZE < ScreenDimensions.y) {
//Top-Left = 0 | Top-Right = 1
//Bottom-Left = 2 | Bottom-Right = 3
vec4 ScreenCoords[4];
ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); // Z-axis might need to be 1
ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
vec3 ViewVectors[4];
for(int i = 0; i < 4; i++) {
ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i]));
}
vec3 EyePos = vec3(0,0,0);
Frustum f;
f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]);
f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]);
f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]);
f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]);
//Top-Left = 0 | Top-Right = 1
//Bottom-Left = 2 | Bottom-Right = 3
vec4 ScreenCoords[4];
ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f;
vec3 ViewVectors[4];
for(int i = 0; i < 4; i++) {
ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i]));
}
vec3 EyePos = vec3(0.0, 0.0 ,0.0);
Frustum f;
f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); // left plane
f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); // right plane
f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); // top plane
f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); // bottom plane
if ( gl_GlobalInvocationID.x < ScreenDimensions.x / TILE_SIZE && gl_GlobalInvocationID.y < ScreenDimensions.y / TILE_SIZE ) { // inside the screen
Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*int(ScreenDimensions.x/TILE_SIZE)] = f;
}
}
-3
View File
@@ -1,8 +1,5 @@
#version 430
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform vec2 PickingColor;
in VertexData{
+1 -1
View File
@@ -22,7 +22,7 @@ out VertexData{
void main()
{
gl_Position = P*V*M * vec4(Position, 1.0);
gl_Position = P * V* M * vec4(Position, 1.0);
Output.Position = Position;
}
-35
View File
@@ -1,35 +0,0 @@
#version 430
//in uvec3 gl_NumWorkGroups;
//in uvec3 gl_WorkGroupID;
//in uvec3 gl_LocalInvocationID;
//in uvec3 gl_GlobalInvocationID;
//in uint gl_LocalInvocationIndex;
#define NUM_LIGHTS 3
#define MAX_LIGHTS_PER_TILE 200
#define NUM_TILES 3600
struct Plane {
vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
layout (std430, binding = 0) buffer FrustumBuffer
{
Frustum Data[3600];
} Frustums;
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main ()
{
if(1 == 1) {
}
}
+9 -2
View File
@@ -9,8 +9,8 @@ find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
find_package(Xerces REQUIRED)
# Because FindOpenAL is retarded
#set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/deps/include/AL")
#find_package(OpenAL REQUIRED)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/deps/include/OpenAL")
find_package(OpenAL REQUIRED)
if(UNIX)
find_package(X11 REQUIRED)
endif()
@@ -52,6 +52,12 @@ file(GLOB SOURCE_FILES_Network
)
source_group(Network FILES ${SOURCE_FILES_Network})
file(GLOB SOURCE_FILES_Sound
"${INCLUDE_PATH}/Sound/*.h"
"Sound/*.cpp"
)
source_group(Sound FILES ${SOURCE_FILES_Sound})
file(GLOB SOURCE_FILES_Rendering
"${INCLUDE_PATH}/Rendering/*.h"
"Rendering/*.cpp"
@@ -86,6 +92,7 @@ set(SOURCE_FILES
${SOURCE_FILES_Core_Util}
${SOURCE_FILES_Input}
${SOURCE_FILES_Network}
${SOURCE_FILES_Sound}
${SOURCE_FILES_GUI}
${SOURCE_FILES_Rendering}
${SOURCE_FILES_Rendering_Util}
+181 -181
View File
@@ -8,196 +8,196 @@
namespace Collision
{
//note: this one hasnt been delta adjusted like RayVsAABB has
bool RayAABBIntr(const Ray& ray, const AABB& box)
{
glm::vec3 w = 75.0f * ray.Direction();
glm::vec3 v = glm::abs(w);
glm::vec3 c = ray.Origin() - box.Center() + w;
glm::vec3 half = box.HalfSize();
//note: this one hasnt been delta adjusted like RayVsAABB has
bool RayAABBIntr(const Ray& ray, const AABB& box)
{
glm::vec3 w = 75.0f * ray.Direction();
glm::vec3 v = glm::abs(w);
glm::vec3 c = ray.Origin() - box.Center() + w;
glm::vec3 half = box.HalfSize();
if (abs(c.x) > v.x + half.x) {
return false;
}
if (abs(c.y) > v.y + half.y) {
return false;
}
if (abs(c.z) > v.z + half.z) {
return false;
}
if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) {
return false;
}
if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) {
return false;
}
return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x);
if (abs(c.x) > v.x + half.x) {
return false;
}
bool RayVsAABB(const Ray& ray, const AABB& box)
{
float dummy;
return RayVsAABB(ray, box, dummy);
if (abs(c.y) > v.y + half.y) {
return false;
}
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
{
glm::vec3 invdir = 1.0f / ray.Direction();
glm::vec3 origin = ray.Origin();
float t1 = (box.MinCorner().x - origin.x)*invdir.x;
float t2 = (box.MaxCorner().x - origin.x)*invdir.x;
float t3 = (box.MinCorner().y - origin.y)*invdir.y;
float t4 = (box.MaxCorner().y - origin.y)*invdir.y;
float t5 = (box.MinCorner().z - origin.z)*invdir.z;
float t6 = (box.MaxCorner().z - origin.z)*invdir.z;
float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));
//if (tmax < 0 || tmin > tmax)
//if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly
//greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax
if (tmax < 0 || tmin>(tmax + 0.0001f))
return false;
outDistance = (tmin > 0) ? tmin : tmax;
return true;
}
bool AABBVsAABB(const AABB& a, const AABB& b)
{
const glm::vec3& aCenter = a.Center();
const glm::vec3& bCenter = b.Center();
const glm::vec3& aHSize = a.HalfSize();
const glm::vec3& bHSize = b.HalfSize();
//Test will probably exit because of the X and Z axes more often, so test them first.
if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) {
return false;
}
if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) {
return false;
}
return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1]));
}
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation)
{
minimumTranslation = glm::vec3(0, 0, 0);
const glm::vec3& aMax = a.MaxCorner();
const glm::vec3& bMax = b.MaxCorner();
const glm::vec3& aMin = a.MinCorner();
const glm::vec3& bMin = b.MinCorner();
const glm::vec3& bSize = b.Size();
const glm::vec3& aSize = a.Size();
float minOffset = INFINITY;
float off;
auto axisesIntersecting = glm::tvec3<bool, glm::highp>(false, false, false);
for (int i = 0; i < 3; ++i) {
off = bMax[i] - aMin[i];
if (off > 0 && off < bSize[i] + aSize[i]) {
if (off < minOffset) {
minimumTranslation = glm::vec3();
minimumTranslation[i] = minOffset = off;
}
axisesIntersecting[i] = true;
}
off = aMax[i] - bMin[i];
if (off > 0 && off < bSize[i] + aSize[i]) {
if (off < minOffset) {
minOffset = off;
minimumTranslation = glm::vec3();
minimumTranslation[i] = -off;
}
axisesIntersecting[i] = true;
}
}
return glm::all(axisesIntersecting);
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices)
{
for (int i = 0; i < modelIndices.size(); ++i) {
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
glm::vec3 m = ray.Origin() - v0;
glm::vec3 MxE1 = glm::cross(m, e1);
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);
float DetInv = glm::dot(e1, DxE2);
if (std::abs(DetInv) < FLT_EPSILON) {
continue;
}
DetInv = 1.0f / DetInv;
float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) {
continue;
}
//Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit.
if (0 <= glm::dot(e2, MxE1) * DetInv) {
return true;
}
}
if (abs(c.z) > v.z + half.z) {
return false;
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
float& outDistance,
float& outUCoord,
float& outVCoord)
{
outDistance = INFINITY;
bool hit = false;
for (int i = 0; i < modelIndices.size(); ++i) {
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
glm::vec3 m = ray.Origin() - v0;
glm::vec3 MxE1 = glm::cross(m, e1);
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec
float DetInv = glm::dot(e1, DxE2);
if (std::abs(DetInv) < FLT_EPSILON) {
continue;
}
DetInv = 1.0f / DetInv;
float dist = glm::dot(e2, MxE1) * DetInv;
if (dist >= outDistance) {
continue;
}
float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) {
return false;
}
if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) {
return false;
}
return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x);
}
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
//If u and v are positive, u+v <= 1, dist is positive, and less than closest.
if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) {
outDistance = dist;
outUCoord = u;
outVCoord = v;
hit = true;
bool RayVsAABB(const Ray& ray, const AABB& box)
{
float dummy;
return RayVsAABB(ray, box, dummy);
}
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
{
glm::vec3 invdir = 1.0f / ray.Direction();
glm::vec3 origin = ray.Origin();
float t1 = (box.MinCorner().x - origin.x)*invdir.x;
float t2 = (box.MaxCorner().x - origin.x)*invdir.x;
float t3 = (box.MinCorner().y - origin.y)*invdir.y;
float t4 = (box.MaxCorner().y - origin.y)*invdir.y;
float t5 = (box.MinCorner().z - origin.z)*invdir.z;
float t6 = (box.MaxCorner().z - origin.z)*invdir.z;
float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));
//if (tmax < 0 || tmin > tmax)
//if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly
//greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax
if (tmax < 0 || tmin>(tmax + 0.0001f))
return false;
outDistance = (tmin > 0) ? tmin : tmax;
return true;
}
bool AABBVsAABB(const AABB& a, const AABB& b)
{
const glm::vec3& aCenter = a.Center();
const glm::vec3& bCenter = b.Center();
const glm::vec3& aHSize = a.HalfSize();
const glm::vec3& bHSize = b.HalfSize();
//Test will probably exit because of the X and Z axes more often, so test them first.
if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) {
return false;
}
if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) {
return false;
}
return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1]));
}
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation)
{
minimumTranslation = glm::vec3(0, 0, 0);
const glm::vec3& aMax = a.MaxCorner();
const glm::vec3& bMax = b.MaxCorner();
const glm::vec3& aMin = a.MinCorner();
const glm::vec3& bMin = b.MinCorner();
const glm::vec3& bSize = b.Size();
const glm::vec3& aSize = a.Size();
float minOffset = INFINITY;
float off;
auto axisesIntersecting = glm::tvec3<bool, glm::highp>(false, false, false);
for (int i = 0; i < 3; ++i) {
off = bMax[i] - aMin[i];
if (off > 0 && off < bSize[i] + aSize[i]) {
if (off < minOffset) {
minimumTranslation = glm::vec3();
minimumTranslation[i] = minOffset = off;
}
axisesIntersecting[i] = true;
}
off = aMax[i] - bMin[i];
if (off > 0 && off < bSize[i] + aSize[i]) {
if (off < minOffset) {
minOffset = off;
minimumTranslation = glm::vec3();
minimumTranslation[i] = -off;
}
axisesIntersecting[i] = true;
}
return hit;
}
return glm::all(axisesIntersecting);
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
glm::vec3& outHitPosition)
{
float u;
float v;
float dist;
bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v);
outHitPosition = ray.Origin() + dist * ray.Direction();
return hit;
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices)
{
for (int i = 0; i < modelIndices.size(); ++i) {
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
glm::vec3 m = ray.Origin() - v0;
glm::vec3 MxE1 = glm::cross(m, e1);
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);
float DetInv = glm::dot(e1, DxE2);
if (std::abs(DetInv) < FLT_EPSILON) {
continue;
}
DetInv = 1.0f / DetInv;
float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) {
continue;
}
//Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit.
if (0 <= glm::dot(e2, MxE1) * DetInv) {
return true;
}
}
return false;
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
float& outDistance,
float& outUCoord,
float& outVCoord)
{
outDistance = INFINITY;
bool hit = false;
for (int i = 0; i < modelIndices.size(); ++i) {
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
glm::vec3 m = ray.Origin() - v0;
glm::vec3 MxE1 = glm::cross(m, e1);
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec
float DetInv = glm::dot(e1, DxE2);
if (std::abs(DetInv) < FLT_EPSILON) {
continue;
}
DetInv = 1.0f / DetInv;
float dist = glm::dot(e2, MxE1) * DetInv;
if (dist >= outDistance) {
continue;
}
float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
//If u and v are positive, u+v <= 1, dist is positive, and less than closest.
if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) {
outDistance = dist;
outUCoord = u;
outVCoord = v;
hit = true;
}
}
return hit;
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
glm::vec3& outHitPosition)
{
float u;
float v;
float dist;
bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v);
outHitPosition = ray.Origin() + dist * ray.Direction();
return hit;
}
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon)
{
@@ -225,11 +225,11 @@ bool attachAABBComponentFromModel(World* world, EntityID id)
return false;
}
glm::mat4 modelMatrix = modelRes->m_Matrix;
glm::mat4 modelMatrix = modelRes->Matrix();
glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY);
glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY);
for (const auto& v : modelRes->m_Vertices) {
for (const auto& v : modelRes->Vertices()) {
const auto& wPos = modelMatrix * glm::vec4(v.Position.x, v.Position.y, v.Position.z, 1);
maxi.x = std::max(wPos.x, maxi.x);
maxi.y = std::max(wPos.y, maxi.y);
@@ -255,7 +255,7 @@ bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox)
if (modelRes == nullptr) {
return false;
}
glm::mat4 modelMatrix = modelRes->m_Matrix *
glm::mat4 modelMatrix = modelRes->Matrix() *
glm::translate(glm::mat4(), (glm::vec3)cTrans["Position"]) *
glm::scale((glm::vec3)cTrans["Scale"]);
+1 -1
View File
@@ -20,7 +20,7 @@ void EntityFile::Parse(const EntityFileHandler* handler) const
{
using namespace xercesc;
EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader);
EntityFileSAXHandler saxHandler(handler, nullptr);
m_SAX2XMLReader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
m_SAX2XMLReader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
m_SAX2XMLReader->setContentHandler(&saxHandler);
+2 -2
View File
@@ -9,10 +9,10 @@ EntityFileParser::EntityFileParser(const EntityFile* entityFile)
m_Handler.SetStartFieldDataCallback(std::bind(&EntityFileParser::onFieldData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}
void EntityFileParser::MergeEntities(World* world, EntityID parent /*= EntityID_Invalid*/)
void EntityFileParser::MergeEntities(World* world)
{
m_World = world;
m_EntityIDMapper[EntityID_Invalid] = parent;
m_EntityIDMapper[0] = 0;
m_EntityFile->Parse(&m_Handler);
}
+2 -1
View File
@@ -144,10 +144,11 @@ void EntityFilePreprocessor::parseComponentInfo()
}
auto& field = compInfo.Fields[name];
field.Name = name;
field.Type = type;
field.Offset = fieldOffset;
field.Stride = stride;
compInfo.FieldsInOrder.push_back(&field);
compInfo.FieldsInOrder.push_back(name);
fieldOffset += stride;
}
+5
View File
@@ -0,0 +1,5 @@
#include "Core/MemoryPool.h"
namespace DisableMemoryPool
{
bool Value = false;
}
+56 -48
View File
@@ -1,4 +1,7 @@
#include "Core/ResourceManager.h"
#include "boost/thread/thread.hpp"
#include "boost/thread/mutex.hpp"
#include "boost/thread/lock_guard.hpp"
std::unordered_map<std::string, std::string> ResourceManager::m_CompilerTypenameToResourceType;
std::unordered_map<std::string, std::function<Resource*(std::string)>> ResourceManager::m_FactoryFunctions;
@@ -6,10 +9,13 @@ std::unordered_map<std::pair<std::string, std::string>, Resource*> ResourceManag
std::unordered_map<std::string, Resource*> ResourceManager::m_ResourceFromName;
std::unordered_map<Resource*, Resource*> ResourceManager::m_ResourceParents;
unsigned int ResourceManager::m_CurrentResourceTypeID = 0;
bool ResourceManager::UseThreading = false;
std::unordered_map<std::string, unsigned int> ResourceManager::m_ResourceTypeIDs;
std::unordered_map<unsigned int, unsigned int> ResourceManager::m_ResourceCount;
bool ResourceManager::m_Preloading = false;
FileWatcher ResourceManager::m_FileWatcher;
std::unordered_map<std::pair<std::string, std::string>, boost::thread> ResourceManager::m_LoadingThreads;
std::unordered_map<std::pair<std::string, std::string>, std::exception_ptr> ResourceManager::m_LoadingThreadExceptions;
boost::recursive_mutex ResourceManager::m_Mutex;
unsigned int ResourceManager::GetTypeID(std::string resourceType)
{
@@ -74,63 +80,65 @@ void ResourceManager::Update()
m_FileWatcher.Check();
}
void ResourceManager::Preload(std::string resourceType, std::string resourceName)
{
if (IsResourceLoaded(resourceType, resourceName)) {
//LOG_WARNING("Attempted to preload resource \"%s\" multiple times!", resourceName.c_str());
return;
}
m_Preloading = true;
LOG_INFO("Preloading resource \"%s\"", resourceName.c_str());
CreateResource(resourceType, resourceName, nullptr);
m_Preloading = false;
}
Resource* ResourceManager::Load(std::string resourceType, std::string resourceName, Resource* parent /*= nullptr*/)
{
auto it = m_ResourceCache.find(std::make_pair(resourceType, resourceName));
if (it != m_ResourceCache.end()) {
return it->second;
}
if (m_Preloading) {
LOG_INFO("Preloading resource \"%s\"", resourceName.c_str());
} else {
LOG_WARNING("Hot-loading resource \"%s\"", resourceName.c_str());
}
return CreateResource(resourceType, resourceName, parent);
}
Resource* ResourceManager::CreateResource(std::string resourceType, std::string resourceName, Resource* parent)
Resource* ResourceManager::createResource(const std::string& resourceType, const std::string& resourceName, Resource* parent, std::exception_ptr& exception)
{
auto facIt = m_FactoryFunctions.find(resourceType);
if (facIt == m_FactoryFunctions.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceType.c_str());
return nullptr;
cacheResource(nullptr, resourceType, resourceName, parent);
//This basically throws an exception.
exception = std::make_exception_ptr(Resource::FailedLoadingException()); return nullptr;
}
// Call the factory function
Resource* resource;
try {
resource = facIt->second(resourceName);
return cacheResource(facIt->second(resourceName), resourceType, resourceName, parent);
} catch (const Resource::StillLoadingException&) {
exception = std::current_exception(); return nullptr;
} catch (const std::exception& e) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": %s", resourceName.c_str(), resourceType.c_str(), e.what());
cacheResource(nullptr, resourceType, resourceName, parent);
exception = std::current_exception(); return nullptr;
}
}
Resource* ResourceManager::createResourceThrowing(const std::string& resourceType, const std::string& resourceName, Resource* parent)
{
std::exception_ptr exception;
Resource* res = createResource(resourceType, resourceName, parent, exception);
if (exception) {
std::rethrow_exception(exception);
}
return res;
}
Resource* ResourceManager::cacheResource(Resource* resource, const std::string& resourceType, const std::string& resourceName, Resource* parent)
{
//Lock the mutex immediately, and unlock it when leaving the code block.
boost::lock_guard<decltype(m_Mutex)> guard(m_Mutex);
if (resource != nullptr) {
// Store IDs
resource->TypeID = GetTypeID(resourceType);
resource->ResourceID = GetNewResourceID(resource->TypeID);
} catch (const std::exception& e) {
resource = nullptr;
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": %s", resourceName.c_str(), resourceType.c_str(), e.what());
}
// Cache
m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource;
m_ResourceFromName[resourceName] = resource;
if (parent != nullptr) {
m_ResourceParents[resource] = parent;
}
if (!boost::filesystem::is_directory(resourceName)) {
LOG_DEBUG("Adding watch for %s", resourceName.c_str());
m_FileWatcher.AddWatch(resourceName, fileWatcherCallback);
}
return resource;
// Cache
m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource;
m_ResourceFromName[resourceName] = resource;
if (parent != nullptr) {
m_ResourceParents[resource] = parent;
}
//if (!boost::filesystem::is_directory(resourceName)) {
// LOG_DEBUG("Adding watch for %s", resourceName.c_str());
// m_FileWatcher.AddWatch(resourceName, fileWatcherCallback);
//}
return resource;
}
bool ResourceManager::IsMainThread()
{
static boost::thread::id MainThreadId = boost::this_thread::get_id();
return boost::this_thread::get_id() == MainThreadId;
}
+52
View File
@@ -0,0 +1,52 @@
#include "Core/Transform.h"
glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity)
{
glm::vec3 position;
while (entity != EntityID_Invalid) {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
EntityID parent = world->GetParent(entity);
position += Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"];
entity = parent;
}
return position;
}
glm::quat Transform::AbsoluteOrientation(World* world, EntityID entity)
{
glm::quat orientation;
while (entity != EntityID_Invalid) {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation;
entity = world->GetParent(entity);
}
return orientation;
}
glm::vec3 Transform::AbsoluteScale(World* world, EntityID entity)
{
glm::vec3 scale(1.f);
while (entity != EntityID_Invalid) {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
scale *= (glm::vec3)transform["Scale"];
entity = world->GetParent(entity);
}
return scale;
}
glm::mat4 Transform::ModelMatrix(EntityID entity, World* world)
{
glm::vec3 position = Transform::AbsolutePosition(world, entity);
glm::quat orientation = Transform::AbsoluteOrientation(world, entity);
glm::vec3 scale = Transform::AbsoluteScale(world, entity);
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(orientation) * glm::scale(scale);
return modelMatrix;
}
+18 -17
View File
@@ -19,7 +19,6 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer)
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease);
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove);
EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking);
EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped);
}
@@ -34,7 +33,7 @@ void EditorSystem::Update(World* world, double dt)
if (!m_Visible) {
return;
}
Picking();
updateWidget();
drawUI(world, dt);
@@ -125,10 +124,13 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
if (m_Selection == 0) {
return false;
}
if (m_Camera == nullptr) {
return false;
}
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
glm::vec3 widgetOrientation = widgetTransform["Orientation"];
glm::quat totalOrientation = m_Renderer->Camera()->Orientation() * glm::inverse(glm::quat(widgetOrientation));
glm::quat totalOrientation = m_Camera->Orientation() * glm::inverse(glm::quat(widgetOrientation));
int width;
int height;
@@ -140,14 +142,14 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
delta2,
m_WidgetPickingDepth,
res,
m_Renderer->Camera()->ProjectionMatrix(),
m_Camera->ProjectionMatrix(),
glm::toMat4(glm::inverse(totalOrientation))
);
glm::vec3 origin = ScreenCoords::ToWorldPos(
glm::vec2(res.Width / 2.f, res.Height / 2.f),
m_WidgetPickingDepth,
res,
m_Renderer->Camera()->ProjectionMatrix(),
m_Camera->ProjectionMatrix(),
glm::toMat4(glm::inverse(totalOrientation))
);
deltaWorld = deltaWorld - origin;
@@ -160,7 +162,7 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
EntityID parent = m_World->GetParent(m_Selection);
glm::quat inverseParentOrientation;
//if (parent != 0) {
inverseParentOrientation = glm::inverse(RenderQueueFactory::AbsoluteOrientation(m_World, parent));
inverseParentOrientation = glm::inverse(Transform::AbsoluteOrientation(m_World, parent));
//}
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * movement;
} else if (m_WidgetSpace == WidgetSpace::Local) {
@@ -176,10 +178,10 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
EntityID parent = m_World->GetParent(m_Selection);
glm::quat parentOrientation;
//if (parent != 0) {
// parentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, parent);
// parentOrientation = RenderSystem::AbsoluteOrientation(m_World, parent);
//}
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
glm::quat currentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection);
glm::quat currentOrientation = Transform::AbsoluteOrientation(m_World, m_Selection);
//glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation);
glm::quat deltaOrientation(finalMovement);
selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation));
@@ -235,10 +237,10 @@ bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e)
return true;
}
bool EditorSystem::OnPicking(const Events::Picking& e)
void EditorSystem::Picking()
{
for (auto& pos : m_PickingQueue) {
auto result = e.Pick(pos);
auto result = m_Renderer->Pick(pos);
EntityID entity = result.Entity;
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
// ???
@@ -246,6 +248,7 @@ bool EditorSystem::OnPicking(const Events::Picking& e)
LOG_INFO("Selected %i", entity);
if (entity != EntityID_Invalid) {
EntityID parent = m_World->GetParent(entity);
m_Camera = result.Camera;
if (parent == m_Widget) {
m_WidgetCurrentAxis = glm::vec3(
(entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ),
@@ -253,7 +256,6 @@ bool EditorSystem::OnPicking(const Events::Picking& e)
(entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY)
);
m_WidgetPickingDepth = result.Depth;
//auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
//auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
//widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"];
@@ -269,7 +271,6 @@ bool EditorSystem::OnPicking(const Events::Picking& e)
}
}
m_PickingQueue.clear();
return true;
};
bool EditorSystem::OnFileDropped(const Events::FileDropped& e)
@@ -323,10 +324,10 @@ void EditorSystem::updateWidget()
if (m_Selection != EntityID_Invalid) {
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
glm::vec3 selectionPosition = RenderQueueFactory::AbsolutePosition(m_World, m_Selection);
glm::vec3 selectionPosition = Transform::AbsolutePosition(m_World, m_Selection);
widgetTransform["Position"] = selectionPosition;
if (m_WidgetSpace == WidgetSpace::Local) {
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
}
@@ -361,7 +362,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode)
if (m_Selection != EntityID_Invalid) {
if (m_WidgetSpace == WidgetSpace::Local) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
} else if (newMode == WidgetMode::Scale) {
@@ -372,7 +373,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode)
m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj";
if (m_Selection != EntityID_Invalid) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
} else if (newMode == WidgetMode::Rotate) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj";
@@ -381,7 +382,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode)
if (m_Selection != EntityID_Invalid) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
if (m_WidgetSpace == WidgetSpace::Local) {
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
}
+50 -47
View File
@@ -17,7 +17,6 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService)
Client::~Client()
{
}
void Client::Start(World* world, EventBroker* eventBroker)
@@ -27,14 +26,8 @@ void Client::Start(World* world, EventBroker* eventBroker)
m_World = world;
// Subscribe to events
m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1));
m_EventBroker->Subscribe(m_EInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand);
//while (m_PlayerName.size() > 7) {
// LOG_INFO("Please enter your name (No longer than 7 characters):");
// std::cin >> m_PlayerName;
//}
m_Socket.connect(m_ReceiverEndpoint);
LOG_INFO("I am client. BIP BOP");
}
@@ -44,18 +37,9 @@ void Client::Update()
readFromServer();
}
void Client::Close()
{
if (m_WasStarted) {
disconnect();
m_ThreadIsRunning = false;
m_EventBroker->Unsubscribe(m_EInputCommand);
}
}
void Client::readFromServer()
{
if (m_Socket.available()) {
while (m_Socket.available()) {
bytesRead = receive(readBuf, INPUTSIZE);
if (bytesRead > 0) {
Packet packet(readBuf, bytesRead);
@@ -65,7 +49,7 @@ void Client::readFromServer()
std::clock_t currentTime = std::clock();
if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) {
if (isConnected()) {
sendSnapshotToServer();
//sendSnapshotToServer();
}
previousSnapshotMessage = currentTime;
}
@@ -73,13 +57,12 @@ void Client::readFromServer()
void Client::sendSnapshotToServer()
{
// Reset previouse key state in snapshot.
// Reset previous key state in snapshot.
m_NextSnapshot.InputForward = "";
m_NextSnapshot.InputRight = "";
auto player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
// See if any movement keys are down
// We dont care if it's overwritten by later
// if statement. Watcha gonna do, right!
@@ -125,6 +108,8 @@ void Client::parseMessageType(Packet& packet)
// Read packet ID
m_PreviousPacketID = m_PacketID; // Set previous packet id
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
if (m_PacketID <= m_PreviousPacketID)
return;
//IdentifyPacketLoss();
switch (static_cast<MessageType>(messageType)) {
@@ -184,33 +169,51 @@ void Client::parseEventMessage(Packet& packet)
}
}
void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
{
for (auto field : componentInfo.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
if (fieldInfo.Type == "string") {
std::string& value = packet.ReadString();
m_World->GetComponent(entityID, componentType)[fieldInfo.Name] = value;
} else {
memcpy(m_World->GetComponent(entityID, componentType).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
}
}
}
// Field parse
void Client::parseSnapshot(Packet& packet)
{
std::string tempName;
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
// We're checking for empty name for now. This might not be the best way,
// but it is to avoid sending redundant data.
tempName = packet.ReadString();
// Apply the position data read to the player entity
// New player connected on the server side
if (m_PlayerDefinitions[i].Name == "" && tempName != "") {
m_PlayerDefinitions[i].Name = tempName;
m_PlayerDefinitions[i].EntityID = createPlayer();
} else if (m_PlayerDefinitions[i].Name != "" && tempName == "") {
// Someone disconnected
// TODO: Insert code here
break;
} else if (m_PlayerDefinitions[i].Name == "" && tempName == "") {
// Not a connected player
break;
}
if (m_PlayerDefinitions[i].EntityID != -1) {
// Move player to server position
int dataSize = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Info.Meta.Stride;
memcpy(m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Data, packet.ReadData(dataSize), dataSize);
std::string componentType = packet.ReadString();
while (packet.DataReadSize() < packet.Size()) {
EntityID entityID = packet.ReadPrimitive<EntityID>();
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
if (m_World->ValidEntity(entityID)) {
if (m_World->HasComponent(entityID, componentType)) {
// If the entity and the component exists update it
updateFields(packet, componentInfo, entityID, componentType);
// if entity exists but not the component
} else {
// Create component
m_World->AttachComponent(entityID, componentType);
// Copy data to newly created component
updateFields(packet, componentInfo, entityID, componentType);
}
// If the entity dosent exist nor the component
} else {
//Create Entity
// If entity dosen't exist
EntityID newEntityID = m_World->CreateEntity();
// Check if EntityIDs are out of sync
if (newEntityID != entityID) {
LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \
same as the one sent by server (EntityIDs are out of sync)");
}
// Create component
m_World->AttachComponent(newEntityID, componentType);
// Copy data to newly created component
updateFields(packet, componentInfo, newEntityID, componentType);
}
}
}
@@ -225,7 +228,7 @@ int Client::receive(char* data, size_t length)
0, error);
if (error) {
//LOG_ERROR("receive: %s", error.message().c_str());
LOG_ERROR("receive: %s", error.message().c_str());
}
return bytesReceived;
+40 -11
View File
@@ -3,13 +3,7 @@
Packet::Packet(MessageType type, unsigned int& packetID)
{
m_Data = new char[m_MaxPacketSize];
// Create message header
// Add message type
int messageType = static_cast<int>(type);
Packet::WritePrimitive<int>(messageType);
packetID = packetID % 1000; // Packet id modulos
Packet::WritePrimitive<int>(packetID);
packetID++;
Init(type, packetID);
}
// Create message
@@ -28,12 +22,26 @@ Packet::~Packet()
delete[] m_Data;
}
void Packet::WriteString(std::string str)
void Packet::Init(MessageType type, unsigned int & packetID)
{
m_ReturnDataOffset = 0;
m_Offset = 0;
// Create message header
// Add message type
int messageType = static_cast<int>(type);
Packet::WritePrimitive<int>(messageType);
packetID = packetID % 1000; // Packet id modulos
Packet::WritePrimitive<int>(packetID);
packetID++;
}
void Packet::WriteString(const std::string& str)
{
// Message, add one extra byte for null terminator
int sizeOfString = str.size() + 1;
if (m_Offset + sizeOfString > m_MaxPacketSize) {
LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size.\n");
LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2);
resizeData();
}
memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char));
m_Offset += sizeOfString * sizeof(char);
@@ -42,7 +50,8 @@ void Packet::WriteString(std::string str)
void Packet::WriteData(char * data, int sizeOfData)
{
if (m_Offset + sizeOfData > m_MaxPacketSize) {
LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size.\n");
LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2);
resizeData();
}
memcpy(m_Data + m_Offset, data, sizeOfData);
m_Offset += sizeOfData;
@@ -69,4 +78,24 @@ char * Packet::ReadData(int SizeOfData)
unsigned int oldReturnDataOffset = m_ReturnDataOffset;
m_ReturnDataOffset += SizeOfData;
return (m_Data + oldReturnDataOffset);
}
}
void Packet::resizeData()
{
// Allocate memory to store our data in
char* holdData = new char[m_MaxPacketSize];
// Copy our data to the newly allocated memory
memcpy(holdData, m_Data, m_Offset);
// Increase max packet size
m_MaxPacketSize = m_MaxPacketSize * 2;
// Delete our data
delete m_Data;
// Allocate twice the memory we had before
m_Data = new char[m_MaxPacketSize];
// Copy our data to new location
memcpy(m_Data, holdData, m_Offset);
// Delete the memory allocated to hold our data
// while we resized the old data container.
delete holdData;
}
+29 -28
View File
@@ -4,7 +4,9 @@ Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::a
{ }
Server::~Server()
{ }
{
}
void Server::Start(World* world, EventBroker* eventBroker)
@@ -22,18 +24,9 @@ void Server::Update()
readFromClients();
}
void Server::Close()
{
m_ThreadIsRunning = false;
}
void Server::readFromClients()
{
// m_ThreadIsRunning might be unnecessary but the
// program crashed if it executed m_Socket.available()
// when closing the program.
if (m_Socket.available()) {
while (m_Socket.available()) {
try {
bytesRead = receive(readBuffer, INPUTSIZE);
Packet packet(readBuffer, bytesRead);
@@ -41,7 +34,6 @@ void Server::readFromClients()
} catch (const std::exception& err) {
//LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what());
}
}
std::clock_t currentTime = std::clock();
// Send snapshot
@@ -58,7 +50,7 @@ void Server::readFromClients()
// Time out logic
if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) {
checkForTimeOuts();
//checkForTimeOuts();
timOutTimer = currentTime;
}
}
@@ -108,7 +100,7 @@ int Server::receive(char * data, size_t length)
void Server::send(Packet& packet, int playerID)
{
m_Socket.send_to(
int bytesSent = m_Socket.send_to(
boost::asio::buffer(packet.Data(), packet.Size()),
m_PlayerDefinitions[playerID].Endpoint,
0);
@@ -150,22 +142,32 @@ void Server::broadcast(Packet& packet)
}
}
// Send snapshot fields
void Server::sendSnapshot()
{
Packet packet(MessageType::Snapshot, m_SendPacketID);
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
// Should time this
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
for (auto& it : worldComponentPools) {
Packet packet(MessageType::Snapshot, m_SendPacketID);
std::string componentType = it.first;
ComponentPool* componentPool = it.second;
ComponentInfo componentInfo = componentPool->ComponentInfo();
packet.WriteString(componentInfo.Name);
// Send an empty name if there is no player connected on this position.
packet.WriteString(m_PlayerDefinitions[i].Name);
if (m_PlayerDefinitions[i].EntityID == -1) {
continue;
for (auto& componentWrapper : *componentPool) {
packet.WritePrimitive(componentWrapper.EntityID);
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
if (fieldInfo.Type == "string") {
std::string& value = componentWrapper[componentField];
packet.WriteString(value);
} else {
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride);
}
}
}
// Pack transfrom component into data packet
auto transform = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform");
packet.WriteData(transform.Data, transform.Info.Meta.Stride);
broadcast(packet);
}
broadcast(packet);
}
void Server::sendPing()
@@ -174,10 +176,9 @@ void Server::sendPing()
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
int ping = 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
LOG_INFO("%i: Player %i's ping: %i", m_PacketID, i, ping);
LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PacketID, i, ping);
}
}
// Create ping message
Packet packet(MessageType::ServerPing, m_SendPacketID);
packet.WriteString("Ping from server");
@@ -271,7 +272,7 @@ void Server::parseConnect(Packet& packet)
m_StopTimes[i] = std::clock();
LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name, m_PlayerDefinitions[i].Endpoint.address().to_string());
LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str());
Packet packet(MessageType::Connect, m_SendPacketID);
packet.WritePrimitive<int>(i); // Player ID
+12 -9
View File
@@ -50,6 +50,18 @@ void Camera::SetOrientation(glm::quat val)
UpdateViewMatrix();
}
void Camera::SetProjectionMatrix(glm::mat4 val)
{
m_ProjectionMatrix = val;
}
void Camera::SetViewMatrix(glm::mat4 val)
{
m_ViewMatrix = val;
}
//void Camera::Pitch(float val)
//{
// m_Pitch = val;
@@ -64,15 +76,6 @@ void Camera::SetOrientation(glm::quat val)
void Camera::UpdateProjectionMatrix()
{
// m_ProjectionMatrix = glm::ortho(
// -16.f,
// 16.f,
// -9.f,
// 9.f,
// m_NearClip,
// m_FarClip
// );
m_ProjectionMatrix = glm::perspective(m_FOV, m_AspectRatio, m_NearClip, m_FarClip);
}
+66
View File
@@ -0,0 +1,66 @@
#include "Rendering/DrawFinalPass.h"
DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass)
{
m_Renderer = renderer;
m_LightCullingPass = lightCullingPass;
InitializeTextures();
InitializeShaderPrograms();
}
void DrawFinalPass::InitializeTextures()
{
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
}
void DrawFinalPass::InitializeShaderPrograms()
{
m_ForwardPlusProgram = ResourceManager::Load<ShaderProgram>("#ForwardPlusProgram");
m_ForwardPlusProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlus.vert.glsl")));
m_ForwardPlusProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlus.frag.glsl")));
m_ForwardPlusProgram->Compile();
m_ForwardPlusProgram->Link();
}
void DrawFinalPass::Draw(RenderScene& scene)
{
GLERROR("DrawFinalPass::Draw: Pre");
DrawFinalPassState state;
m_ForwardPlusProgram->Bind();
GLuint shaderHandle = m_ForwardPlusProgram->GetHandle();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
//TODO: Render: Add code for more jobs than modeljobs.
for (auto &job : scene.ForwardJobs) {
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if(modelJob) {
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
if(modelJob->DiffuseTexture != nullptr) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
} else {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
}
glBindVertexArray(modelJob->Model->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
continue;
}
}
GLERROR("DrawFinalPass::Draw: END");
}
@@ -0,0 +1,18 @@
#include "Rendering/DrawFinalPassState.h"
DrawFinalPassState::DrawFinalPassState()
{
BindFramebuffer(0);
Enable(GL_BLEND);
BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Enable(GL_DEPTH_TEST);
Enable(GL_CULL_FACE);
ClearColor(glm::vec4(200.f / 255, 0.f / 255, 200.f / 255, 0.f));
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
DrawFinalPassState::~DrawFinalPassState()
{
}
+11 -15
View File
@@ -14,36 +14,31 @@ void DrawScenePass::InitializeTextures()
void DrawScenePass::InitializeShaderPrograms()
{
//Gör så att shaders är en resource, tex som texture classen. Konstruktorn måste vara privat.
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#BasicForwardProgram");
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
m_BasicForwardProgram->Compile();
m_BasicForwardProgram->Link();
}
void DrawScenePass::Draw(RenderQueueCollection& rq)
void DrawScenePass::Draw(RenderScene& scene)
{
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLERROR("Renderer::Draw PickingPass");
GLERROR("DrawScenePass::Draw: Pre");
DrawScenePassState state;
DrawScenePassState state = DrawScenePassState();
m_BasicForwardProgram->Bind();
//TODO: Render: Add code for more jobs than modeljobs.
for (auto &job : rq.Forward) {
for (auto &job : scene.ForwardJobs) {
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if (modelJob) {
GLuint ShaderHandle = m_BasicForwardProgram->GetHandle();
m_BasicForwardProgram->Bind();
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
//TODO: Renderer: bättre textur felhantering samt fler texturer stöd
@@ -59,8 +54,9 @@ void DrawScenePass::Draw(RenderQueueCollection& rq)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
continue;
//continue;
}
}
GLERROR("DrawScene Error");
GLERROR("DrawScenePass::Draw: End");
}
+4 -2
View File
@@ -8,8 +8,10 @@ DrawScenePassState::DrawScenePassState()
GLERROR("---");
Enable(GL_DEPTH_TEST);
Enable(GL_CULL_FACE);
ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f));
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Enable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f));
// Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
DrawScenePassState::~DrawScenePassState()

Some files were not shown because too many files have changed in this diff Show More