From a630067068f9b6d122765f553efc8490ef8005b1 Mon Sep 17 00:00:00 2001 From: Shao Kun Deng Date: Tue, 7 Oct 2014 15:55:04 -0400 Subject: [PATCH] Added files from previous projects --- .gitattributes | 63 +++++++ .gitignore | 4 + Readme.txt | 6 + astria.sln | 22 +++ astria/Agent.cpp | 42 +++++ astria/Agent.h | 50 ++++++ astria/Common.h | 14 ++ astria/Event.cpp | 267 ++++++++++++++++++++++++++++ astria/Event.h | 65 +++++++ astria/FPS.cpp | 47 +++++ astria/FPS.h | 30 ++++ astria/FileManager.cpp | 136 ++++++++++++++ astria/FileManager.h | 38 ++++ astria/Gene.cpp | 247 ++++++++++++++++++++++++++ astria/Gene.h | 77 ++++++++ astria/Light.cpp | 23 +++ astria/Light.h | 23 +++ astria/Log.cpp | 17 ++ astria/Log.h | 31 ++++ astria/Main.cpp | 48 +++++ astria/Main.h | 118 +++++++++++++ astria/Main_OnEvent.cpp | 93 ++++++++++ astria/Main_OnExit.cpp | 16 ++ astria/Main_OnInit.cpp | 158 +++++++++++++++++ astria/Main_OnRender.cpp | 41 +++++ astria/Main_OnUpdate.cpp | 39 ++++ astria/Model.cpp | 156 ++++++++++++++++ astria/Model.h | 47 +++++ astria/NeuralNet.cpp | 183 +++++++++++++++++++ astria/NeuralNet.h | 53 ++++++ astria/Object.h | 31 ++++ astria/Params.cpp | 56 ++++++ astria/Params.h | 59 +++++++ astria/Shader.cpp | 323 ++++++++++++++++++++++++++++++++++ astria/Shader.h | 92 ++++++++++ astria/Skybox.cpp | 105 +++++++++++ astria/Skybox.h | 29 +++ astria/State.cpp | 29 +++ astria/State.h | 35 ++++ astria/StaticObj.cpp | 41 +++++ astria/StaticObj.h | 8 + astria/Stringify.cpp | 97 ++++++++++ astria/Stringify.h | 32 ++++ astria/Texture.cpp | 272 ++++++++++++++++++++++++++++ astria/Texture.h | 64 +++++++ astria/VBO.cpp | 78 ++++++++ astria/VBO.h | 41 +++++ astria/astria.vcxproj | 117 ++++++++++++ astria/astria.vcxproj.filters | 174 ++++++++++++++++++ astria/utils.h | 25 +++ 50 files changed, 3862 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Readme.txt create mode 100644 astria.sln create mode 100644 astria/Agent.cpp create mode 100644 astria/Agent.h create mode 100644 astria/Common.h create mode 100644 astria/Event.cpp create mode 100644 astria/Event.h create mode 100644 astria/FPS.cpp create mode 100644 astria/FPS.h create mode 100644 astria/FileManager.cpp create mode 100644 astria/FileManager.h create mode 100644 astria/Gene.cpp create mode 100644 astria/Gene.h create mode 100644 astria/Light.cpp create mode 100644 astria/Light.h create mode 100644 astria/Log.cpp create mode 100644 astria/Log.h create mode 100644 astria/Main.cpp create mode 100644 astria/Main.h create mode 100644 astria/Main_OnEvent.cpp create mode 100644 astria/Main_OnExit.cpp create mode 100644 astria/Main_OnInit.cpp create mode 100644 astria/Main_OnRender.cpp create mode 100644 astria/Main_OnUpdate.cpp create mode 100644 astria/Model.cpp create mode 100644 astria/Model.h create mode 100644 astria/NeuralNet.cpp create mode 100644 astria/NeuralNet.h create mode 100644 astria/Object.h create mode 100644 astria/Params.cpp create mode 100644 astria/Params.h create mode 100644 astria/Shader.cpp create mode 100644 astria/Shader.h create mode 100644 astria/Skybox.cpp create mode 100644 astria/Skybox.h create mode 100644 astria/State.cpp create mode 100644 astria/State.h create mode 100644 astria/StaticObj.cpp create mode 100644 astria/StaticObj.h create mode 100644 astria/Stringify.cpp create mode 100644 astria/Stringify.h create mode 100644 astria/Texture.cpp create mode 100644 astria/Texture.h create mode 100644 astria/VBO.cpp create mode 100644 astria/VBO.h create mode 100644 astria/astria.vcxproj create mode 100644 astria/astria.vcxproj.filters create mode 100644 astria/utils.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0699a58 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.sdf +*.v12.suo +/Debug/ +Debug/ \ No newline at end of file diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 0000000..87920c1 --- /dev/null +++ b/Readme.txt @@ -0,0 +1,6 @@ +Artificial +Self +Teaching +Roaming +Intelligent +Agent \ No newline at end of file diff --git a/astria.sln b/astria.sln new file mode 100644 index 0000000..d97b5c9 --- /dev/null +++ b/astria.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "astria", "astria\astria.vcxproj", "{AA160014-3EA4-4114-B955-031B22CC7A6A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AA160014-3EA4-4114-B955-031B22CC7A6A}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA160014-3EA4-4114-B955-031B22CC7A6A}.Debug|Win32.Build.0 = Debug|Win32 + {AA160014-3EA4-4114-B955-031B22CC7A6A}.Release|Win32.ActiveCfg = Release|Win32 + {AA160014-3EA4-4114-B955-031B22CC7A6A}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/astria/Agent.cpp b/astria/Agent.cpp new file mode 100644 index 0000000..1ca7842 --- /dev/null +++ b/astria/Agent.cpp @@ -0,0 +1,42 @@ +#include "State.h" +#include "Agent.h" +#include "utils.h" + +Agent::Agent() +{ + std::string name = "Individual " + NextValidID; + Agent(name); +} + +Agent::Agent(std::string name) +{ + int x = RandInt(CParams::WorldMinX, CParams::WorldMaxX); + int y = RandInt(CParams::WorldMinY, CParams::WorldMaxY); + int z = CParams::GroundLevel; + Agent(name, x, y, z); +} + +Agent::Agent(std::string name, int x, int y, int z) +{ + Name = name; + Position = glm::vec3(x, y, z); + Look = glm::vec3(0) - Position; + MoveDirection = glm::vec3(0); + Speed = 0; + + CurrentState = new State(); +} + +Agent::~Agent() +{ + +} + +void Agent::ChangeState(State* newState) +{ + assert(CurrentState && newState); + + CurrentState->Exit(this); + CurrentState = newState; + CurrentState->Enter(this); +} \ No newline at end of file diff --git a/astria/Agent.h b/astria/Agent.h new file mode 100644 index 0000000..a7d63ab --- /dev/null +++ b/astria/Agent.h @@ -0,0 +1,50 @@ +#ifndef _AGENT_H_ +#define _AGENT_H_ + +#include "Object.h" +#include "Common.h" + +enum AGENT_STATE +{ + STATE_ROAM, + STATE_FLEE +}; + +class Agent : public Object +{ +public: + Agent(); + Agent(std::string name); + Agent(std::string name, int x, int y, int z); + ~Agent(); + + void Move(float direction, float distance); + + void ChangeState(State* newState); + void Interact(Object* target); + + void Update(); + + vector GetSurrounding(float radius); + vector GetSurrounding(int numObj); + +// Accessor functions +public: + glm::vec3 GetMoveDirection () const { return MoveDirection; } + glm::vec3 GetLook () const { return Look; } + float GetSpeed () const { return Speed; } + State* GetState () const { return CurrentState; } + +private: + std::string Name; + + glm::vec3 Look; + glm::vec3 MoveDirection; + float Speed; + + State* CurrentState; + + +}; + +#endif \ No newline at end of file diff --git a/astria/Common.h b/astria/Common.h new file mode 100644 index 0000000..db02576 --- /dev/null +++ b/astria/Common.h @@ -0,0 +1,14 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +// Include common headers +#include +#include +#include +#include +#include +#include +#include +#include + +#endif \ No newline at end of file diff --git a/astria/Event.cpp b/astria/Event.cpp new file mode 100644 index 0000000..e0d8f4b --- /dev/null +++ b/astria/Event.cpp @@ -0,0 +1,267 @@ +//============================================================================== +#include "Event.h" + +//============================================================================== +CEvent::CEvent() { +} + +//------------------------------------------------------------------------------ +CEvent::~CEvent() { + //Do nothing +} + +//============================================================================== +void CEvent::OnEvent(SDL_Event* Event) { + switch(Event->type) { + //case SDL_ACTIVEEVENT: { + // switch(Event->active.state) { + // case SDL_APPMOUSEFOCUS: { + // if ( Event->active.gain ) OnMouseFocus(); + // else OnMouseBlur(); + + // break; + // } + // case SDL_APPINPUTFOCUS: { + // if ( Event->active.gain ) OnInputFocus(); + // else OnInputBlur(); + + // break; + // } + // case SDL_APPACTIVE: { + // if ( Event->active.gain ) OnRestore(); + // else OnMinimize(); + + // break; + // } + // } + // break; + //} + + case SDL_KEYDOWN: { + OnKeyDown(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.scancode); + break; + } + + case SDL_KEYUP: { + OnKeyUp(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.scancode); + break; + } + + case SDL_MOUSEMOTION: { + OnMouseMove(Event->motion.x,Event->motion.y,Event->motion.xrel,Event->motion.yrel,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_LEFT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_RIGHT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_MIDDLE))!=0); + break; + } + + case SDL_MOUSEBUTTONDOWN: { + switch(Event->button.button) { + case SDL_BUTTON_LEFT: { + OnLButtonDown(Event->button.x,Event->button.y); + break; + } + case SDL_BUTTON_RIGHT: { + OnRButtonDown(Event->button.x,Event->button.y); + break; + } + case SDL_BUTTON_MIDDLE: { + OnMButtonDown(Event->button.x,Event->button.y); + break; + } + } + break; + } + + case SDL_MOUSEBUTTONUP: { + switch(Event->button.button) { + case SDL_BUTTON_LEFT: { + OnLButtonUp(Event->button.x,Event->button.y); + break; + } + case SDL_BUTTON_RIGHT: { + OnRButtonUp(Event->button.x,Event->button.y); + break; + } + case SDL_BUTTON_MIDDLE: { + OnMButtonUp(Event->button.x,Event->button.y); + break; + } + } + break; + } + + case SDL_JOYAXISMOTION: { + OnJoyAxis(Event->jaxis.which,Event->jaxis.axis,Event->jaxis.value); + break; + } + + case SDL_JOYBALLMOTION: { + OnJoyBall(Event->jball.which,Event->jball.ball,Event->jball.xrel,Event->jball.yrel); + break; + } + + case SDL_JOYHATMOTION: { + OnJoyHat(Event->jhat.which,Event->jhat.hat,Event->jhat.value); + break; + } + case SDL_JOYBUTTONDOWN: { + OnJoyButtonDown(Event->jbutton.which,Event->jbutton.button); + break; + } + + case SDL_JOYBUTTONUP: { + OnJoyButtonUp(Event->jbutton.which,Event->jbutton.button); + break; + } + + case SDL_QUIT: { + OnExit(); + break; + } + + case SDL_SYSWMEVENT: { + //Ignore + break; + } + + //case SDL_VIDEORESIZE: { + // OnResize(Event->resize.w,Event->resize.h); + // break; + //} + + //case SDL_VIDEOEXPOSE: { + // OnExpose(); + // break; + //} + + default: { + OnUser(Event->user.type,Event->user.code,Event->user.data1,Event->user.data2); + break; + } + } +} + +//------------------------------------------------------------------------------ +void CEvent::OnInputFocus() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnInputBlur() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnKeyDown(SDL_Keycode sym, Uint16 mod, SDL_Scancode unicode) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnKeyUp(SDL_Keycode sym, Uint16 mod, SDL_Scancode unicode) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMouseFocus() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMouseBlur() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMouseWheel(bool Up, bool Down) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnLButtonDown(int mX, int mY) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnLButtonUp(int mX, int mY) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnRButtonDown(int mX, int mY) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnRButtonUp(int mX, int mY) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMButtonDown(int mX, int mY) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMButtonUp(int mX, int mY) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnJoyAxis(Uint8 which,Uint8 axis,Sint16 value) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnJoyButtonDown(Uint8 which,Uint8 button) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnJoyButtonUp(Uint8 which,Uint8 button) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnJoyHat(Uint8 which,Uint8 hat,Uint8 value) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnJoyBall(Uint8 which,Uint8 ball,Sint16 xrel,Sint16 yrel) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnMinimize() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnRestore() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnResize(int w,int h) { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnExpose() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnExit() { + //Pure virtual, do nothing +} + +//------------------------------------------------------------------------------ +void CEvent::OnUser(Uint8 type, int code, void* data1, void* data2) { + //Pure virtual, do nothing +} + +//============================================================================== diff --git a/astria/Event.h b/astria/Event.h new file mode 100644 index 0000000..0d8c30f --- /dev/null +++ b/astria/Event.h @@ -0,0 +1,65 @@ +#ifndef _CEVENT_H_ +#define _CEVENT_H_ + +#include + +class CEvent { + public: + CEvent(); + + virtual ~CEvent(); + + void OnEvent(SDL_Event* Event); + + virtual void OnInputFocus(); + + virtual void OnInputBlur(); + + virtual void OnKeyDown(SDL_Keycode sym, Uint16 mod, SDL_Scancode unicode); + + virtual void OnKeyUp(SDL_Keycode sym, Uint16 mod, SDL_Scancode unicode); + + virtual void OnMouseFocus(); + + virtual void OnMouseBlur(); + + virtual void OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle); + + virtual void OnMouseWheel(bool Up, bool Down); //Not implemented + + virtual void OnLButtonDown(int mX, int mY); + + virtual void OnLButtonUp(int mX, int mY); + + virtual void OnRButtonDown(int mX, int mY); + + virtual void OnRButtonUp(int mX, int mY); + + virtual void OnMButtonDown(int mX, int mY); + + virtual void OnMButtonUp(int mX, int mY); + + virtual void OnJoyAxis(Uint8 which,Uint8 axis,Sint16 value); + + virtual void OnJoyButtonDown(Uint8 which,Uint8 button); + + virtual void OnJoyButtonUp(Uint8 which,Uint8 button); + + virtual void OnJoyHat(Uint8 which,Uint8 hat,Uint8 value); + + virtual void OnJoyBall(Uint8 which,Uint8 ball,Sint16 xrel,Sint16 yrel); + + virtual void OnMinimize(); + + virtual void OnRestore(); + + virtual void OnResize(int w,int h); + + virtual void OnExpose(); + + virtual void OnExit(); + + virtual void OnUser(Uint8 type, int code, void* data1, void* data2); +}; + +#endif \ No newline at end of file diff --git a/astria/FPS.cpp b/astria/FPS.cpp new file mode 100644 index 0000000..8b87e11 --- /dev/null +++ b/astria/FPS.cpp @@ -0,0 +1,47 @@ +#include "hFPS.h" + +CFPS CFPS::FPSControl; + +CFPS::CFPS() +{ + OldTime = 0; + LastTime = 0; + + SpeedFactor = 0; + + Frames = 0; + NumFrames = 0; +} + +void CFPS::Loop() +{ + //After each second + if(OldTime + 1000 < SDL_GetTicks()) + { + //Clear timer + OldTime = SDL_GetTicks(); + + //Get FPS + NumFrames = Frames; + + //Clear frame count + Frames = 0; + } + + SpeedFactor = ((SDL_GetTicks() - LastTime) / 1000.0f) * 32.0f; + + LastTime = SDL_GetTicks(); + + Frames++; +} + +int CFPS::GetFPS() +{ + return NumFrames; +} + +float CFPS::GetSpeedFactor() +{ + return SpeedFactor; +} + diff --git a/astria/FPS.h b/astria/FPS.h new file mode 100644 index 0000000..2cad523 --- /dev/null +++ b/astria/FPS.h @@ -0,0 +1,30 @@ +#ifndef _CFPS_H_ +#define _CFPS_H_ + +#include + +class CFPS { + public: + static CFPS FPSControl; + + private: + int OldTime; + int LastTime; + + float SpeedFactor; + + int NumFrames; + int Frames; + + public: + CFPS(); + + void Loop(); + + public: + int GetFPS(); + + float GetSpeedFactor(); +}; + +#endif diff --git a/astria/FileManager.cpp b/astria/FileManager.cpp new file mode 100644 index 0000000..223019d --- /dev/null +++ b/astria/FileManager.cpp @@ -0,0 +1,136 @@ +//============================================================================= +#include "FileManager.h" +#include "Log.h" +#include "Stringify.h" + +#if !(defined(_WIN32) || defined(_WIN64)) + #include +#endif +#include "dirent.h" +#include + +//============================================================================= +bool FileManager::SetContents(std::string Filename, std::string Content, bool Relative) { + if(Filename == "") return false; + + if(Relative) Filename = GetCWD() + DIR_SEPARATOR + Filename; + + std::ofstream FileHandle; + + FileHandle.open(Filename.c_str()); + if(!FileHandle.is_open()) return false; + + FileHandle << Content; + FileHandle.close(); + + return true; +} + +//----------------------------------------------------------------------------- +std::string FileManager::GetContents(std::string Filename, bool Relative) { + if(Filename == "") return ""; + + if(Relative) Filename = GetCWD() + DIR_SEPARATOR + Filename; + + std::string Content; + std::ifstream FileHandle; + + FileHandle.open(Filename.c_str()); + + if(FileHandle.is_open()) { + while(FileHandle.good()) { + std::string Buffer; + getline(FileHandle, Buffer); + if(Buffer == "") continue; + + Content += Buffer + "\n"; + } + + FileHandle.close(); + } + + return Content; +} + +//----------------------------------------------------------------------------- +std::vector FileManager::GetFilesInFolder(std::string Folder) { + std::vector List; + + std::string CWD = GetCWD(); + std::string Path = CWD; + + //if(Folder != "") Path += DIR_SEPARATOR + Folder; + if (Folder != "") Path += Folder; + + #ifdef __APPLE__ + NSError* Error; + + NSString* PathNS = [NSString stringWithUTF8String:Path.c_str()]; + NSArray* DirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:PathNS error:&Error]; + + for(id File in DirectoryContents) { + std::string Filename = Path + DIR_SEPARATOR + [File cStringUsingEncoding:1]; + + List.push_back(Filename); + } + #else + DIR* DirHandle = NULL; + dirent* FileHandle = NULL; + + // Needs improved + if((DirHandle = opendir(Folder.c_str())) != NULL) { + while((FileHandle = readdir(DirHandle)) != NULL) { + if(std::string(FileHandle->d_name) == ".") continue; + if(std::string(FileHandle->d_name) == "..") continue; + + std::string Filename = Path + DIR_SEPARATOR + FileHandle->d_name; + + //Log("Found File: %s", Filename.c_str()); + + List.push_back(Filename); + } + + closedir(DirHandle); + }else{ + Log("Unable to open directory : %s", Path.c_str()); + } + #endif + + return List; +} + +//----------------------------------------------------------------------------- +std::string FileManager::GetCWD() { + std::string CWD; + + #ifdef __APPLE__ + NSString* ResourcePath = [[NSBundle mainBundle] resourcePath]; + CWD = [ResourcePath cStringUsingEncoding:1]; + #elseif !(defined(_WIN32) || defined(_WIN64)) + char Buffer[MAXPATHLEN]; + CWD = (getcwd(Buffer, MAXPATHLEN) ? std::string(Buffer) : std::string("")); + #endif + + return CWD; +} + +//----------------------------------------------------------------------------- +std::string FileManager::GetFilenameWithoutExt(std::string Filename) { + std::vector Parts = Stringify::Explode(Filename, DIR_SEPARATOR); + std::string NewFilename = Parts[Parts.size() - 1]; + + // To Do: Filename could potentially have one or more dots + Parts = Stringify::Explode(NewFilename, "."); + NewFilename = Parts[0]; + + return NewFilename; +} + +//----------------------------------------------------------------------------- +std::string FileManager::GetFilenameExt(std::string Filename) { + std::vector Parts = Stringify::Explode(Filename, "."); + + return (Parts.size() <= 1 ? "" : Parts[Parts.size() - 1]); +} + +//============================================================================= diff --git a/astria/FileManager.h b/astria/FileManager.h new file mode 100644 index 0000000..bab21db --- /dev/null +++ b/astria/FileManager.h @@ -0,0 +1,38 @@ +//============================================================================== +/* + Class for loading files and reading directories + + Note: To use iOS functions, set your file type to Objective-C++ + + 3/18/2014 + SDLTutorials.com + Tim Jones +*/ +//============================================================================== +#ifndef __FILEMANAGER_H__ + #define __FILEMANAGER_H__ + +#include +#include +#include +#include +#include + +#define DIR_SEPARATOR "/" + +class FileManager { + public: + static bool SetContents(std::string Filename, std::string Content, bool Relative = true); + + static std::string GetContents(std::string Filename, bool Relative = true); + + static std::vector GetFilesInFolder(std::string Folder); + + static std::string GetCWD(); + + static std::string GetFilenameWithoutExt(std::string Filename); + + static std::string GetFilenameExt(std::string Filename); +}; + +#endif diff --git a/astria/Gene.cpp b/astria/Gene.cpp new file mode 100644 index 0000000..90a1ee4 --- /dev/null +++ b/astria/Gene.cpp @@ -0,0 +1,247 @@ +#include "Gene.h" +#include "Individual.h" + +//CGenAlg::CGenAlg(int popsize, double mutrate, double crossrate, int numweights) : +//PopSize(popsize), +//MutationRate(mutrate), +//CrossoverRate(crossrate), +//ChromoLength(numweights), +//TotalFitness(0), +//generation(0), +//FittestGenome(0), +//BestFitness(0), +//WorstFitness(99999999), +//AverageFitness(0) +//{ +// for (int i = 0; i < PopSize; i++) +// { +// population.push_back(SGenome()); +// for (int j = 0; j < ChromoLength; j++) +// { +// population[i].weights.push_back(RandNormal()); +// } +// } +//} +// +//void CGenAlg::Mutate(vector &chromo) +//{ +// for (int i = 0; i < chromo.size(); i++) +// { +// if (RandFloat() < MutationRate) +// { +// chromo[i] += (RandNormal() * CParams::MaxPerturbation); +// } +// } +//} +// +//SGenome CGenAlg::GetChromoRoulette() +//{ +// double Slice = (double)(RandFloat() * TotalFitness); +// +// SGenome chosen; +// +// double accumulatedFitness = 0; +// +// for (int i = 0; i < PopSize; i++) +// { +// accumulatedFitness += population[i].fitness; +// if (accumulatedFitness > Slice) +// { +// chosen = population[i]; +// break; +// } +// } +// return chosen; +//} +// +//void CGenAlg::Crossover(const vector &mom, +// const vector &dad, +// vector &offspring1, +// vector &offspring2) +//{ +// if ((RandFloat() > CrossoverRate) || (mom == dad)) +// { +// offspring1 = mom; +// offspring2 = dad; +// return; +// } +// +// int cp = RandInt(0, ChromoLength - 1); +// +// for (int i = 0; i < cp; i++) +// { +// offspring1.push_back(mom[i]); +// offspring2.push_back(dad[i]); +// } +// for (int i = cp; i < mom.size(); i++) +// { +// offspring1.push_back(mom[i]); +// offspring2.push_back(dad[i]); +// } +// return; +//} +// +//vector CGenAlg::Epoch(vector &old_pop) +//{ +// //assign the given population to the classes population +// population = old_pop; +// +// //reset the appropriate variables +// reset(); +// +// //sort the population (for scaling and elitism) +// sort(population.begin(), population.end()); +// +// //calculate best, worst, average and total fitness +// calBestWorstAvTot(); +// +// //create a temporary vector to store new chromosones +// vector vecNewPop; +// +// //Now to add a little elitism we shall add in some copies of the +// //fittest genomes. Make sure we add an EVEN number or the roulette +// //wheel sampling will crash +// if (!(CParams::NumCopiesElite * CParams::NumElite % 2)) +// { +// GrabBest(CParams::NumElite, CParams::NumCopiesElite, vecNewPop); +// } +// +// +// //now we enter the GA loop +// +// //repeat until a new population is generated +// while (vecNewPop.size() < PopSize) +// { +// //grab two chromosones +// SGenome mom = GetChromoRoulette(); +// SGenome dad = GetChromoRoulette(); +// +// //create some offspring via crossover +// vector baby1, baby2; +// +// Crossover(mom.weights, dad.weights, baby1, baby2); +// +// //now we mutate +// Mutate(baby1); +// Mutate(baby2); +// +// //now copy into vecNewPop population +// vecNewPop.push_back(SGenome(baby1, 0)); +// vecNewPop.push_back(SGenome(baby2, 0)); +// } +// +// //finished so assign new pop back into m_vecPop +// population = vecNewPop; +// +// return population; +//} +// +//void CGenAlg::GrabBest(int best, const int numCopies, vector &pop) +//{ +// while (best--) +// { +// for (int i = 0; i < numCopies; i++) +// { +// pop.push_back(population[(PopSize - 1) - best]); +// } +// } +//} +// +//void CGenAlg::calBestWorstAvTot() +//{ +// TotalFitness = 0; +// +// double HighestSoFar = 0; +// double LowestSoFar = 9999999; +// +// for (int i = 0; i HighestSoFar) +// { +// HighestSoFar = population[i].fitness; +// +// FittestGenome = i; +// +// BestFitness = HighestSoFar; +// } +// +// //update worst if necessary +// if (population[i].fitness < LowestSoFar) +// { +// LowestSoFar = population[i].fitness; +// +// WorstFitness = LowestSoFar; +// } +// +// TotalFitness += population[i].fitness; +// +// +// }//next chromo +// +// AverageFitness = TotalFitness / PopSize; +//} +// +////-------------------------Reset()------------------------------ +//// +//// resets all the relevant variables ready for a new generation +////-------------------------------------------------------------- +//void CGenAlg::reset() +//{ +// TotalFitness = 0; +// BestFitness = 0; +// WorstFitness = 9999999; +// AverageFitness = 0; +//} + +void CGenAlg::GetOffSpring(CIndividual* dad, CIndividual* mom) +{ + if (dad == mom || !dad->CanMate() || !mom->CanMate()) + { + return; + } + + vector NewDNA(dad->GetDNA().size()); + + for (int i = 0; i < NewDNA.size(); i++) + { + if (RandFloat() <= CParams::CrossoverRate) + { + CrossOver(dad->GetDNA()[i], mom->GetDNA()[i], NewDNA[i]); + } + + if (RandFloat() <= CParams::MutationRate) + { + Mutate(NewDNA[i]); + } + } + + SVector2D NewPosition((dad->position.x - mom->position.x) / 2, (dad->position.y - mom->position.y) / 2); + + CIndividual::Population.push_back(new CIndividual(NewPosition.x, NewPosition.y, NewDNA)); +} + +void CGenAlg::CrossOver(const vector & dad, const vector & mom, vector & offspring) +{ + int cp = RandInt(0, dad.size()); + + for (int i = 0; i < cp; i++) + { + offspring.push_back(dad[i]); + } + for (int i = cp; i < mom.size(); i++) + { + offspring.push_back(mom[i]); + } +} + +void CGenAlg::Mutate(vector & chromosome) +{ + for (int i = 0; i < chromosome.size(); i++) + { + if (RandFloat() < CParams::MutationRate) + { + chromosome[i] += (RandNormal() * CParams::MaxPerturbation); + } + } +} \ No newline at end of file diff --git a/astria/Gene.h b/astria/Gene.h new file mode 100644 index 0000000..2ab795d --- /dev/null +++ b/astria/Gene.h @@ -0,0 +1,77 @@ +#ifndef _GENE_H_ +#define _GENE_H_ + +#include +#include +#include "Params.h" +#include "utils.h" + +using namespace std; + +//struct SGenome +//{ +// vector weights; +// SGenome(vector w) :weights(w){} +//}; + +enum GENE_INDEX +{ + GENE_INDEX_MOVEMENT = 0, + GENE_INDEX_SURROUNDING, + GENE_INDEX_ACTION, + GENE_COUNT +}; + +typedef vector SGenome; + +class CIndividual; + +class CGenAlg +{ +public: + static void GetOffSpring(CIndividual* dad, CIndividual* mom); +private: + static void CrossOver(const vector & dad, const vector & mom, vector & offspring); + static void Mutate(vector & chromosome); +}; + + +//class CGenAlg +//{ +//private: +// vector population; +// int PopSize; +// int ChromoLength; +// double TotalFitness; +// double BestFitness; +// double AverageFitness; +// double WorstFitness; +// double FittestGenome; +// double MutationRate; +// double CrossoverRate; +// int generation; +// void Crossover(const vector &mom, +// const vector &dad, +// vector &offspring1, +// vector &offspring2); +// void Mutate(vector &chromo); +// SGenome GetChromoRoulette(); +// void GrabBest(int best, const int numCopies, vector &pop); +// void calBestWorstAvTot(); +// void reset(); +// +//public: +// CGenAlg(int popsize, double mutrate, double crossrate, int numweights); +// +// vector Epoch(vector &old_pop); +// +// vector GetChromo() const { +// return population; +// } +// +// double avgFitness() const { return TotalFitness / PopSize; } +// +// double bestFitness() const { return BestFitness; } +//}; + +#endif \ No newline at end of file diff --git a/astria/Light.cpp b/astria/Light.cpp new file mode 100644 index 0000000..2e76187 --- /dev/null +++ b/astria/Light.cpp @@ -0,0 +1,23 @@ +#include "Light.h" + +CDirectLight::CDirectLight() +{ + color = glm::vec3(1.0f, 1.0f, 1.0f); + direction = glm::vec3(0.0f, -1.0f, 0.0f); + + ambient = 0.25f; +} + +CDirectLight::CDirectLight(glm::vec3 color, glm::vec3 direction, float ambient) +{ + this->color = color; + this->direction = direction; + this->ambient = ambient; +} + +void CDirectLight::setUniform(CShaderProgram* program, std::string lightVarName) +{ + program->SetUniform(lightVarName + ".vColor", color); + program->SetUniform(lightVarName + ".vDirection", direction); + program->SetUniform(lightVarName + ".fAmbient", ambient); +} \ No newline at end of file diff --git a/astria/Light.h b/astria/Light.h new file mode 100644 index 0000000..4d85a21 --- /dev/null +++ b/astria/Light.h @@ -0,0 +1,23 @@ +#ifndef _LIGHT_H_ +#define _LIGHT_H_ + +#include + +#include "Shader.h" +#include + +class CDirectLight +{ +public: + glm::vec3 color; //color of light + glm::vec3 direction; + + float ambient; + + void setUniform(CShaderProgram* program, std::string lightVarName); + + CDirectLight(); + CDirectLight(glm::vec3 color, glm::vec3 direction, float ambient); +}; + +#endif \ No newline at end of file diff --git a/astria/Log.cpp b/astria/Log.cpp new file mode 100644 index 0000000..e122d33 --- /dev/null +++ b/astria/Log.cpp @@ -0,0 +1,17 @@ +#include "Log.h" + +void Log(...) +{ + va_list arglist; + va_start(arglist, arg); + +#if _DEBUG + cout << arg << ' '; + va_end(arglist); + cout << endl; + +#else + MessageBox(NULL, arg, "Error", MB_ICON_ERROR); + va_end(arglist); +#endif +} \ No newline at end of file diff --git a/astria/Log.h b/astria/Log.h new file mode 100644 index 0000000..fda30be --- /dev/null +++ b/astria/Log.h @@ -0,0 +1,31 @@ +//============================================================================== +/* + Basic macro for logging (can be extended for other target builds; i.e, using + NSLog for OS X / iOS). Could also be modified to log to a file instead of + console. + + 3/11/2014 + SDLTutorials.com + Tim Jones +*/ +//============================================================================== + +#pragma once + +#ifndef __LOG_H__ + #define __LOG_H__ + + #define _DEBUG 1 + #include + #if _DEBUG + #include + + #include + #include + #define Log(...) printf(__VA_ARGS__); printf("\n\n"); + #else + #define NDEBUG + #include + #endif + +#endif diff --git a/astria/Main.cpp b/astria/Main.cpp new file mode 100644 index 0000000..5e309d4 --- /dev/null +++ b/astria/Main.cpp @@ -0,0 +1,48 @@ +#include "Main.h" + +CMain::CMain() +{ + Running = true; + Window_Main = NULL; + + Speed = 5.0f; + MouseSpeed = 0.002f; +} + +CMain* CMain::GetInstance() +{ + return &Instance; +} + +int CMain::OnExecute() +{ + if (!OnInit()) + { + return -1; + } + + SDL_Event Event; + + while (Running) + { + while (SDL_PollEvent(&Event)) + { + OnEvent(Event); + } + + OnUpdate(); + + OnRender(); + + } + + OnExit(); + + return 0; +} + +int main(int argc, char* argv[]) +{ + CMain::GetInstance()->OnExecute(); + return 0; +} \ No newline at end of file diff --git a/astria/Main.h b/astria/Main.h new file mode 100644 index 0000000..3715b7b --- /dev/null +++ b/astria/Main.h @@ -0,0 +1,118 @@ +/*The main header, contains most of the program flow functions +*/ + +#ifndef _H_MAIN_ +#define _H_MAIN_ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "Model.h" +#include "Event.h" +#include "FPS.h" +#include "Shader.h" +#include "Skybox.h" +#include "Light.h" +#include "StaticObj.h" + +#define _DEBUG 1 + +class CMain : public CEvent +{ +public: + CMain(); + + static CMain* GetInstance(); + + //Program entry point + int OnExecute(); + + //Initiate the program + bool OnInit(); + //Initiate graphics and OpenGL related contents + bool OnInit_GL(); + + //Handle Events + void OnEvent(SDL_Event Event); + + //Update on each frame + void OnUpdate(); + + //Handle rendering + void OnRender(); + + //Cleanup the program upon exiting + void OnExit(); + +private: + bool Running; + static CMain Instance; + + SDL_Window* Window_Main; + SDL_GLContext glContext; + + const int OPENGL_MAJOR_VERSION = 3; + const int OPENGL_MINOR_VERSION = 3; + +private: + //Event variables + int Mouse_X; //Mouse x position + int Mouse_Y; //Mouse y position + + //Event functions + void OnKeyDown(SDL_Keycode sym, Uint16 mod, SDL_Scancode unicode); + +private: + //Shaders & Shader programs + CShader mainShader_vertex; + CShader mainShader_fragment; + //CShader ortho2D_vertex; + //CShader ortho2D_fragment; + CShader lightShader_fragment; + CShaderProgram mainProgram; + + //Skybox and lighting + CSkybox skybox; + CDirectLight sun; + + //Scene obj + CVBO scene_VBO; + GLuint scene_VAO; + CTexture scene_texture; + + CModel models[2]; + GLuint PolyMode; + + //Matrices + glm::mat4 Projection; + glm::mat4 View; + glm::mat4 Model; + glm::mat4 MVP; + glm::mat4 ModelView; + glm::mat3 ModelView3x3; + +private: //Movements and related Matrix transformations + glm::vec3 Position; //Position of the camera + float HorizontalAngle; //Horizontal viewing angle + float VerticalAngle; //Vertical viewing angle + float FoV; //Field of view + + glm::vec3 Direction; + glm::vec3 Right; + + float Speed; //Speed of movements + float MouseSpeed; +}; + +#endif \ No newline at end of file diff --git a/astria/Main_OnEvent.cpp b/astria/Main_OnEvent.cpp new file mode 100644 index 0000000..dea1cb1 --- /dev/null +++ b/astria/Main_OnEvent.cpp @@ -0,0 +1,93 @@ +#include "hMain.h" + +void CMain::OnEvent(SDL_Event Event) +{ + if(Event.type == SDL_QUIT) + { + Running = false; + } + + CEvent::OnEvent(&Event); + + if (Event.type == SDL_MOUSEWHEEL) + { + FoV -= 5 * Event.wheel.y; + if (FoV > 80) + { + FoV = 80; + } + if (FoV < 20) + { + FoV = 20; + } + } + + //Get mouse position + SDL_GetMouseState(&Mouse_X, &Mouse_Y); + + //Recenter mouse + SDL_WarpMouseInWindow(Window_Main, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); + + //Compute new orientation + HorizontalAngle += MouseSpeed * float(SCREEN_WIDTH / 2 - Mouse_X); + VerticalAngle += MouseSpeed * float(SCREEN_HEIGHT / 2 - Mouse_Y); +} + +void CMain::OnKeyDown(SDL_Keycode sym, Uint16 mod, SDL_Scancode unicode) +{ + std::string pos = std::to_string(Position.x) + ' ' + std::to_string(Position.y) + ' ' + std::to_string(Position.z); + std::string angle = std::to_string(HorizontalAngle) + ' ' + std::to_string(VerticalAngle); + + switch (sym) + { + //Terminate the program if the user press Esc or LeftAlt+F4 + case SDLK_ESCAPE: + Running = false; + break; + case SDLK_F4: + if (unicode == SDL_SCANCODE_LALT) + { + Running = false; + } + break; + case SDLK_w: + case SDLK_UP: + Position += Direction * Speed * CFPS::FPSControl.GetSpeedFactor(); + break; + case SDLK_s: + case SDLK_DOWN: + Position -= Direction * Speed *CFPS::FPSControl.GetSpeedFactor(); + break; + case SDLK_d: + case SDLK_RIGHT: + Position += Right * Speed *CFPS::FPSControl.GetSpeedFactor(); + break; + case SDLK_a: + case SDLK_LEFT: + Position -= Right * Speed *CFPS::FPSControl.GetSpeedFactor(); + break; + +#ifdef _DEBUG + //Switch between normal model and wireframe + case SDLK_q: + if (PolyMode == GL_FILL) + { + PolyMode = GL_LINE; + glPolygonMode(GL_FRONT_AND_BACK, PolyMode); + } + else if (PolyMode == GL_LINE) + { + PolyMode = GL_FILL; + glPolygonMode(GL_FRONT_AND_BACK, PolyMode); + } + break; +#endif + + case SDLK_F1: + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Position", pos.c_str(), NULL); + break; + case SDLK_F2: + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Angles", angle.c_str(), NULL); + break; + } +} diff --git a/astria/Main_OnExit.cpp b/astria/Main_OnExit.cpp new file mode 100644 index 0000000..d3120d9 --- /dev/null +++ b/astria/Main_OnExit.cpp @@ -0,0 +1,16 @@ +#include "hMain.h" + +void CMain::OnExit() +{ + mainShader_vertex.release(); + mainShader_fragment.release(); + lightShader_fragment.release(); + mainProgram.release(); + skybox.release(); + + SDL_DestroyWindow(Window_Main); + Window_Main = NULL; + + IMG_Quit(); + SDL_Quit(); +} \ No newline at end of file diff --git a/astria/Main_OnInit.cpp b/astria/Main_OnInit.cpp new file mode 100644 index 0000000..cfa544a --- /dev/null +++ b/astria/Main_OnInit.cpp @@ -0,0 +1,158 @@ +#include "hMain.h" + +bool CMain::OnInit() +{ + //Initialize SDL + if(SDL_Init(SDL_INIT_VIDEO) < 0) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL initiation error", SDL_GetError(), NULL); + return false; + } + +#ifdef _DEBUG + //Enable console output + freopen("CON", "w", stdout); // redirects stdout + freopen("CON", "w", stderr); // redirects stderr +#endif + + //Initialize SDL_image for texture and image loading + if(IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL_image initiation", IMG_GetError(), NULL); + return false; + } + + //Set OpenGL 3.3 core + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_MAJOR_VERSION); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_MINOR_VERSION); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); //Enable core profil + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); //Backward compatibility + + //User interaction before the creation of the main window + //- Fullscreen + int FullscreenOption = MessageBox(NULL, "Enable fullscreen?", "Fullscreen", MB_ICONQUESTION | MB_YESNO); + + //Create Window + switch (FullscreenOption) + { + case IDNO: + Window_Main = SDL_CreateWindow(WINDOW_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); + break; + case IDYES: + Window_Main = SDL_CreateWindow(WINDOW_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN); + } + if(Window_Main == NULL) + { + MessageBox(NULL, SDL_GetError(), "Window creation error", MB_ICONERROR); + return false; + } + + //Create OpenGL context + glContext = SDL_GL_CreateContext(Window_Main); + if(glContext == NULL) + { + MessageBox(NULL, SDL_GetError(), "OpenGL context creation failed!", MB_ICONERROR); + return false; + } + + //Initialize GLEW + glewExperimental = GL_TRUE; + GLenum glewInitStatus = glewInit(); + if(glewInitStatus != GLEW_OK) + { + MessageBox(NULL, (char*)(glewGetErrorString(glewInitStatus)), "GLEW initialization failed!", MB_ICONERROR); + return false; + } + + //Enable Vsync + if (SDL_GL_SetSwapInterval(1) < 0) + { + MessageBox(NULL, SDL_GetError(), "Warning: Unable to set VSync!", MB_ICONWARNING); + } + + + //Initialize OpenGL components + if(!OnInit_GL()) + { + return false; + } + + //Hide mouse cursor + if (SDL_ShowCursor(SDL_DISABLE) < 0) + { + MessageBox(NULL, SDL_GetError(), "Warning: Unable to hide cursor", MB_ICONWARNING); + } + + //Center mouse cursor + SDL_WarpMouseInWindow(Window_Main, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); + + return true; +} + +bool CMain::OnInit_GL() +{ + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + //Remove triangles which normal is not towards the camera (do not render the inside of the model) + // glEnable(GL_CULL_FACE); + + + //Load shader + if (!mainShader_vertex.load("shaders/main_shader.vert", GL_VERTEX_SHADER)) + return false; + if (!mainShader_fragment.load("shaders/main_shader.frag", GL_FRAGMENT_SHADER)) + return false; + if (!lightShader_fragment.load("shaders/dirLight.frag", GL_FRAGMENT_SHADER)) + return false; + if (!mainProgram.initiate(3, &mainShader_vertex, &mainShader_fragment, &lightShader_fragment)) + return false; + + + //Load models + models[0].load("gfx/Wolf/Wolf.obj"); + models[1].load("gfx/house/house.3ds"); + CModel::finalizeVBO(); + + PolyMode = GL_FILL; + + //Model matrix //Identity matrix + Model = glm::mat4(1.0f); + + //Clear the background as dark blue + glClearColor(0.1f, 0.1f, 0.4f, 0.0f); + + //skybox.load("gfx/skybox_elbrus/elbrus_front.jpg", + // "gfx/skybox_elbrus/elbrus_back.jpg", + // "gfx/skybox_elbrus/elbrus_right.jpg", + // "gfx/skybox_elbrus/elbrus_left.jpg", + // "gfx/skybox_elbrus/elbrus_top.jpg", + // "gfx/skybox_elbrus/elbrus_top.jpg"); + + skybox.load("gfx/mp_hexagon/hexagon_ft.tga", + "gfx/mp_hexagon/hexagon_bk.tga", + "gfx/mp_hexagon/hexagon_lf.tga", + "gfx/mp_hexagon/hexagon_rt.tga", + "gfx/mp_hexagon/hexagon_up.tga", + "gfx/mp_hexagon/hexagon_dn.tga"); + + //skybox.load("gfx/mp_chlorine/chlorine-bay_ft.tga", + // "gfx/mp_chlorine/chlorine-bay_bk.tga", + // "gfx/mp_chlorine/chlorine-bay_lf.tga", + // "gfx/mp_chlorine/chlorine-bay_rt.tga", + // "gfx/mp_chlorine/chlorine-bay_up.tga", + // "gfx/mp_chlorine/chlorine-bay_dn.tga"); + + sun = CDirectLight(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(sqrt(2.0f) / 2, -sqrt(2.0f) / 2, 0), 1.0f); + + CreateStaticSceneObjects(&scene_VAO, scene_VBO); + scene_texture.load_2D("gfx/sand_grass_02.jpg", true); + scene_texture.setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP); + + Position = glm::vec3(30, 5, 30); + FoV = 45.0f; + HorizontalAngle = -3.14f; + VerticalAngle = 0.0f; + + return true; +} \ No newline at end of file diff --git a/astria/Main_OnRender.cpp b/astria/Main_OnRender.cpp new file mode 100644 index 0000000..05ac6b3 --- /dev/null +++ b/astria/Main_OnRender.cpp @@ -0,0 +1,41 @@ +#include "hMain.h" + +void CMain::OnRender() +{ + //Clear the screen for each frame + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //Use shaders + mainProgram.use(); + + mainProgram.SetUniform("matrices.projMatrix", Projection); + mainProgram.SetUniform("matrices.viewMatrix", View); + mainProgram.SetUniform("gSampler", 0); + + mainProgram.SetUniform("matrices.modelMatrix", Model); + mainProgram.SetUniform("matrices.normalMatrix", glm::mat4(1.0)); + mainProgram.SetUniform("vColor", glm::vec4(1, 1, 1, 1)); + + sun.setUniform(&mainProgram, "sunLight"); + + mainProgram.SetUniform("matrices.modelMatrix", glm::translate(glm::mat4(1.0), Position)); + skybox.render(); + + mainProgram.SetUniform("matrices.modelMatrix", glm::mat4(1.0)); + + //Render ground + glBindVertexArray(scene_VAO); + scene_texture.bind(); + glDrawArrays(GL_TRIANGLES, 0, 6); + + //Render models + CModel::bindVAO(); + float xPosHouse = -80.0f + 30.0f; + glm::mat4 mModel = glm::translate(glm::mat4(1.0), glm::vec3(xPosHouse, 0, 0)); + mModel = glm::scale(mModel, glm::vec3(3, 3, 3)); + mainProgram.SetModelAndNormalMatrix("matrices.modelMatrix", "matrices.normalMatrix", mModel); + models[0].render(); + //models[1].render(); + + SDL_GL_SwapWindow(Window_Main); +} \ No newline at end of file diff --git a/astria/Main_OnUpdate.cpp b/astria/Main_OnUpdate.cpp new file mode 100644 index 0000000..fb5878e --- /dev/null +++ b/astria/Main_OnUpdate.cpp @@ -0,0 +1,39 @@ +#include "hMain.h" + +void CMain::OnUpdate() +{ + //clamp(VerticalAngle, -3.14f / 4.0f, 3.14f / 4.0f); + + //Direction : Spherical coordinates to cartesian coordinates conversion + Direction = glm::vec3( + cos(VerticalAngle) * sin(HorizontalAngle), + sin(VerticalAngle), + cos(VerticalAngle) * cos(HorizontalAngle) + ); + + //Right vector + Right = glm::vec3( + sin(HorizontalAngle - 3.14f / 2.0f), + 0, + cos(HorizontalAngle - 3.14f / 2.0f) + ); + + glm::vec3 up = glm::cross(Right, Direction); + + Projection = glm::perspective(FoV, WINDOW_RATIO, 0.1f, 1000.0f); + + View = glm::lookAt( + Position, + Position + Direction, + up + ); + + ModelView = View * Model; + ModelView3x3 = glm::mat3(ModelView); + MVP = Projection * View * Model; + + CFPS::FPSControl.Loop(); + + std::string Text_FPS = "OpenGL_Test FPS: " + std::to_string(CFPS::FPSControl.GetFPS()); + SDL_SetWindowTitle(Window_Main, Text_FPS.c_str()); +} \ No newline at end of file diff --git a/astria/Model.cpp b/astria/Model.cpp new file mode 100644 index 0000000..c435871 --- /dev/null +++ b/astria/Model.cpp @@ -0,0 +1,156 @@ +#include "Model.h" + +CVBO CModel::vboModelData; + +GLuint CModel::VAO; + +std::vector CModel::textures; + +string GetDirectoryPath(string sFilePath) +{ + // Get directory path + string sDirectory = ""; + for (int i = sFilePath.size() - 1; i >= 0; i--)if (sFilePath[i] == '\\' || sFilePath[i] == '/') + { + sDirectory = sFilePath.substr(0, i + 1); + break; + } + return sDirectory; +} + +CModel::CModel() +{ + loaded = false; +} + +CModel::CModel(char* file) +{ + load(file); +} + +bool CModel::load(char* file) +{ + if (vboModelData.getID() == 0) + { + vboModelData.create(); + textures.reserve(50); + } + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(file, + aiProcess_CalcTangentSpace | + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType); + + if (!scene) + { + std::string errormsg = "Couldn't load model "; + errormsg += file; + MessageBox(NULL, errormsg.c_str(), "Error Importing Asset", MB_ICONERROR); + return false; + } + + const int vertexTotalSize = sizeof(aiVector3D)* 2 + sizeof(aiVector2D); + + int totalVertices = 0; + + for (int i = 0; i < scene->mNumMeshes; i++) + { + aiMesh* mesh = scene->mMeshes[i]; + int iMeshFaces = mesh->mNumFaces; + materialIndices.push_back(mesh->mMaterialIndex); + int iSizeBefore = vboModelData.getCurrentSize(); + meshStartIndices.push_back(iSizeBefore / vertexTotalSize); + for (int j = 0; j < iMeshFaces; j++) + { + const aiFace& face = mesh->mFaces[j]; + for (int k = 0; k < 3; k++) + { + aiVector3D pos = mesh->mVertices[face.mIndices[k]]; + aiVector3D uv = mesh->mTextureCoords[0][face.mIndices[k]]; + aiVector3D normal = mesh->HasNormals() ? mesh->mNormals[face.mIndices[k]] : aiVector3D(1.0f, 1.0f, 1.0f); + vboModelData.addData(&pos, sizeof(aiVector3D)); + vboModelData.addData(&uv, sizeof(aiVector2D)); + vboModelData.addData(&normal, sizeof(aiVector3D)); + } + } + int iMeshVertices = mesh->mNumVertices; + totalVertices += iMeshVertices; + meshSize.push_back((vboModelData.getCurrentSize() - iSizeBefore) / vertexTotalSize); + } + + numMaterials = scene->mNumMaterials; + + vector materialRemap(numMaterials); + + for (int i = 0; i < numMaterials; i++) + { + const aiMaterial* material = scene->mMaterials[i]; + int a = 5; + int texIndex = 0; + aiString path; // filename + + if (material->GetTexture(aiTextureType_DIFFUSE, texIndex, &path) == AI_SUCCESS) + { + string sDir = GetDirectoryPath(file); + string sTextureName = path.data; + string sFullPath = sDir + sTextureName; + int iTexFound = -1; + for (int j = 0; j < textures.size(); j++)if (sFullPath == textures[j].getFile()) + { + iTexFound = j; + break; + } + if (iTexFound != -1)materialRemap[i] = iTexFound; + else + { + CTexture tNew; + tNew.load_2D((char*)sFullPath.c_str(), true); + materialRemap[i] = textures.size(); + textures.push_back(tNew); + } + } + } + + for (int i = 0; i < meshSize.size(); i++) + { + int iOldIndex = materialIndices[i]; + materialIndices[i] = materialRemap[iOldIndex]; + } + return loaded = true; +} + +void CModel::finalizeVBO() +{ + glGenVertexArrays(1, &VAO); + glBindVertexArray(VAO); + vboModelData.bind(); + vboModelData.uploadGPU(GL_STATIC_DRAW); + + //Vertex position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(aiVector3D)+sizeof(aiVector2D), 0); + //Texture coordinates + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(aiVector3D)+sizeof(aiVector2D), (void*)sizeof(aiVector3D)); + //Normal vectors + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(aiVector3D)+sizeof(aiVector2D), (void*)(sizeof(aiVector3D)+sizeof(aiVector2D))); +} + +void CModel::bindVAO() +{ + glBindVertexArray(VAO); +} + +void CModel::render() +{ + if (!loaded) return; + int numMeshes = meshSize.size(); + for (int i = 0; i < numMeshes; i++) + { + int matIndex = materialIndices[i]; + textures[matIndex].bind(); + glDrawArrays(GL_TRIANGLES, meshStartIndices[i], meshSize[i]); + } +} \ No newline at end of file diff --git a/astria/Model.h b/astria/Model.h new file mode 100644 index 0000000..89a3c98 --- /dev/null +++ b/astria/Model.h @@ -0,0 +1,47 @@ +#ifndef _MODEL_H_ +#define _MODEL_H_ + +#include + +// Include AssImp +#include // C++ importer interface +#include // Output data structure +#include // Post processing flags + +#include "hader.h" +#include "VBO.h" +#include "Texture.h" + +class CMaterial +{ +public: + int Texture; +}; + +class CModel +{ +public: + CModel(); + CModel(char* file); + + bool load(char* file); + //bool load_BumpMap(char* file, char* colorMap, char* normalMap); + + static void finalizeVBO(); + static void bindVAO(); + + void render(); + //void render_BumpMap(CShaderProgram* program); + +private: + bool loaded; + static CVBO vboModelData; + static GLuint VAO; + static std::vector textures; + std::vector meshStartIndices; + std::vector meshSize; + std::vector materialIndices; + int numMaterials; +}; + +#endif \ No newline at end of file diff --git a/astria/NeuralNet.cpp b/astria/NeuralNet.cpp new file mode 100644 index 0000000..6494c14 --- /dev/null +++ b/astria/NeuralNet.cpp @@ -0,0 +1,183 @@ +#include "NeuralNet.h" + +// ============================= +// ====== SNeuron Methods ====== +// ============================= + +SNeuron::SNeuron(int numInputs) : NumInputs(numInputs+1) +{ + for (int i = 0; i < numInputs + 1; i++) + { + Weight.push_back(RandNormal()); + } +} + +// =================================== +// ====== SNeuronLayer Methods ======= +// =================================== + +SNeuronLayer::SNeuronLayer(int numNeurons, int numInputsPerNeuron) : NumNeurons(numNeurons) +{ + for (int i = 0; i < numNeurons; i++) + { + Neurons.push_back(SNeuron(numInputsPerNeuron)); + } +} + +// ================================ +// ====== CNeuralNet Methods ====== +// ================================ + +// Setup a neural network +CNeuralNet::CNeuralNet(int Input, int Output, int Hidden, int NeuronsPerHidden) +{ + NumInputs = Input; + NumOutputs = Output; + NumHiddenLayers = Hidden; + NeuronsPerHiddenLayer = NeuronsPerHidden; + + Create(); +} + +// Create a neural network +void CNeuralNet::Create() +{ + //create the layers of the network + if (NumHiddenLayers > 0) + { + //create the first hidden layer + Layers.push_back(SNeuronLayer(NeuronsPerHiddenLayer, NumInputs)); + + for (int i = 0; i < NumHiddenLayers - 1; i++) + { + Layers.push_back(SNeuronLayer(NeuronsPerHiddenLayer, NeuronsPerHiddenLayer)); + } + //create output layer + Layers.push_back(SNeuronLayer(NumOutputs, NeuronsPerHiddenLayer)); + } + else + { + //create output layer + Layers.push_back(SNeuronLayer(NumOutputs, NumInputs)); + } +} + +// Returns a vector containing the weights +vector CNeuralNet::GetWeights() const +{ + //hold all the weights + vector weights; + + //for each layer + for (int i = 0; i < NumHiddenLayers + 1; i++) + { + //for each neuron + for (int j = 0; j < Layers[i].NumNeurons; j++) + { + //for each weight + for (int k = 0; k < Layers[i].Neurons[i].NumInputs; k++) + { + weights.push_back(Layers[i].Neurons[j].Weight[k]); + } + } + } + return weights; +} + +// Replace the weights in the NN with provided weight vector +void CNeuralNet::SetWeights(vector &weights) +{ + int weightIndex = 0; + + //for each layer + for (int i = 0; i < NumHiddenLayers + 1; i++) + { + //for each neuron + for (int j = 0; j < Layers[i].NumNeurons; j++) + { + //for each weight + for (int k = 0; k < Layers[i].Neurons[i].NumInputs; k++) + { + Layers[i].Neurons[j].Weight[k] = weights[weightIndex]; + weightIndex++; + } + } + } +} + +// Return the total number of weights needed for the net +int CNeuralNet::GetNumberOfWeights() const +{ + int NumWeights = 0; + //for each layer + for (int i = 0; i < NumHiddenLayers + 1; i++) + { + //for each neuron + for (int j = 0; j < Layers[i].NumNeurons; j++) + { + //for each weight + for (int k = 0; k < Layers[i].Neurons[i].NumInputs; k++) + { + NumWeights++; + } + } + } + return NumWeights; +} + +// Returns a output vector given an input vector +vector CNeuralNet::Update(vector & inputs) +{ + //stores the resultant output from each layer + vector outputs; + int cWeight = 0; + + //first check that we have the correct amount of inputs + if (inputs.size() != NumInputs) + { + //returns empty vector + return outputs; + } + + //for each layer + for (int i = 0; i < NumHiddenLayers + 1; i++) + { + if (i > 0) + { + inputs = outputs; + } + outputs.clear(); + cWeight = 0; + + //for each neuron sum the (inputs * corresponding weights) + //throw the total at our sigmoid function to get the ouput + for (int j = 0; j < Layers[i].NumNeurons; j++) + { + double netInput = 0; + + int NumInputs = Layers[i].Neurons[j].NumInputs; + + //for each weight + for (int k = 0; k < NumInputs - 1; k++) + { + //sum the weights * inputs + netInput += Layers[i].Neurons[j].Weight[k] * inputs[cWeight++]; + } + //add in the bias + netInput += Layers[i].Neurons[j].Weight[NumInputs - 1] * CParams::Bias; + + //we store the outputs from each layer as we generate them + //the combined activation is first filtered through the sigmoid function + outputs.push_back(Sigmoid(netInput, CParams::ActivationResponse)); + + cWeight = 0; + } + } + return outputs; +} + +// Sigmoid function +double CNeuralNet::Sigmoid(double netInput, double activationResponse) +{ + return (1 / (1 + exp(-netInput / activationResponse))); +} \ No newline at end of file diff --git a/astria/NeuralNet.h b/astria/NeuralNet.h new file mode 100644 index 0000000..25a4853 --- /dev/null +++ b/astria/NeuralNet.h @@ -0,0 +1,53 @@ +#ifndef _NEURAL_NETWORK_H_ +#define _NEURAL_NETWORK_H_ + +#include +#include "utils.h" +#include "Params.h" + +using namespace std; + +struct SNeuron +{ + //number of inputs going into the neuron + int NumInputs; + //weight of each input + vector Weight; + //constructor + SNeuron(int numInputs); +}; + +struct SNeuronLayer +{ + int NumNeurons; + vector Neurons; + SNeuronLayer(int numNeurons, int numInputsPerNeuron); +}; + +class CNeuralNet +{ +public: + CNeuralNet(int Input, int Output, int HiddenLayer, int NeuronsPerHiddenLayer); + //create the net + void Create(); + //get the weights from the neuralnetwork + vector GetWeights() const; + //return the total number of weights in the net + int GetNumberOfWeights() const; + //replaces the weights with new ones + void SetWeights(vector & weights); + //calculates the outputs from a set of inputs + vector Update(vector & inputs); + //sigmoid response curve + inline double Sigmoid(double netInput, double activationResponse); + +private: + int NumInputs; + int NumOutputs; + int NumHiddenLayers; + int NeuronsPerHiddenLayer; + //storage for each layer of neurons including the output layer + vector Layers; +}; + +#endif \ No newline at end of file diff --git a/astria/Object.h b/astria/Object.h new file mode 100644 index 0000000..41225dc --- /dev/null +++ b/astria/Object.h @@ -0,0 +1,31 @@ +#ifndef _OBJECT_H_ +#define _OBJECT_H_ + +enum OBJ_FLAG +{ + FLAG_NONE = 0x00000000, + FLAG_GRAVITY = 0x00000002, + FLAG_GHOST = 0x00000004 +}; + +typedef unsigned int uint; + +class Object +{ +public: + Object() {} + virtual ~Object() {} + glm::vec3 GetPosition () const { return this->Position; } + OBJ_FLAG GetFlag () const { return Flag; } + uint GetID () const { return ID; } + + virtual void Update() = 0; + +protected: + glm::vec3 Position; + OBJ_FLAG Flag; + uint ID; + static uint NextValidID; +}; + +#endif \ No newline at end of file diff --git a/astria/Params.cpp b/astria/Params.cpp new file mode 100644 index 0000000..427683a --- /dev/null +++ b/astria/Params.cpp @@ -0,0 +1,56 @@ +#include "Params.h" + +char* CParams::File = "param.ini"; + +//Set everything to zero before loading the values from .ini file +double CParams::Pi = 3.14159265358979; +double CParams::HalfPi = Pi / 2; +double CParams::TwoPi = Pi * 2; +char* CParams::WindowName = "NeuralNetwork"; +int CParams::WindowWidth = 480; +int CParams::WindowHeight = 360; +int CParams::FoodCount = 10; +int CParams::InitIndividualCount = 10; +double CParams::ActivationResponse = 0; +double CParams::Bias = 0; +double CParams::CrossoverRate = 0; +double CParams::MutationRate = 0; +double CParams::MaxPerturbation = 0; +int CParams::DecayTimeInterval = 0; +int CParams::AgeTimeInterval = 0; +int CParams::MatingCooldown = 1000; + +//Load the paramets from the file +//Return false if failed to load file +bool CParams::Load(char* file) +{ + ifstream inFile(file); + + //Verify file opening + if (!inFile) + { + return false; + } + + //Load from the file + char ParamDescription[40]; + inFile >> ParamDescription >> WindowWidth; + inFile >> ParamDescription >> WindowHeight; + inFile >> ParamDescription >> FoodCount; + inFile >> ParamDescription >> InitIndividualCount; + inFile >> ParamDescription >> ActivationResponse; + inFile >> ParamDescription >> Bias; + inFile >> ParamDescription >> CrossoverRate; + inFile >> ParamDescription >> MutationRate; + inFile >> ParamDescription >> MaxPerturbation; + inFile >> ParamDescription >> DecayTimeInterval; + inFile >> ParamDescription >> AgeTimeInterval; + inFile >> ParamDescription >> MatingCooldown; + + return true; +} + +void CParams::Store(char* file) +{ + +} \ No newline at end of file diff --git a/astria/Params.h b/astria/Params.h new file mode 100644 index 0000000..e44d22d --- /dev/null +++ b/astria/Params.h @@ -0,0 +1,59 @@ +#ifndef _PARAM_H_ +#define _PARAM_H_ + +#include +#include + +using namespace std; + +class CParams +{ +public: + static char* File; + + // ===== General parameters ====== + static double Pi; + static double HalfPi; + static double TwoPi; + + static char* WindowName; + static int WindowWidth; + static int WindowHeight; + + // ===== General properties ===== + static int FoodCount; + static int InitIndividualCount; + + static int WorldMinX, WorldMaxX; + static int WorldMinY, WorldMaxY; + static int WorldMinZ, WorldMaxZ; + static int GroundLevel; + + // ===== Genetic algorithm ===== + static double CrossoverRate; + static double MutationRate; + static double MaxPerturbation; //Maximum amount the genetic algorithm may mutate each weight by + static double ActivationResponse; //For tweaking sigmoid function + static double Bias; //bias value + + // ===== Individual properties ===== + static int DecayTimeInterval; //in millisecond + static int AgeTimeInterval; //in millisecond + + static int MatingCooldown; + + CParams() + { + if (!Load(File)) + { + char* errormsg; + sprintf(errormsg, "Cannot find %s", File); + MessageBox(NULL, errormsg, "Error", MB_ICONERROR); + } + } + + static bool Load(char* file); + static void Store(char* file); +}; + +#endif \ No newline at end of file diff --git a/astria/Shader.cpp b/astria/Shader.cpp new file mode 100644 index 0000000..e6d4b67 --- /dev/null +++ b/astria/Shader.cpp @@ -0,0 +1,323 @@ +#include "Shader.h" +#include +#include +#include +#include +#include + +using namespace std; + +CShader::CShader() +{ + loaded = false; +} + +CShader::~CShader() +{ + release(); +} + +bool CShader::load(string file, int type) +{ + vector sLines; + + if (!GetLinesFromFile(file, false, &sLines))return false; + + const char** sProgram = new const char*[sLines.size()]; + for (int i = 0; i < sLines.size(); i++)sProgram[i] = sLines[i].c_str(); + + shader = glCreateShader(type); + + glShaderSource(shader, sLines.size(), sProgram, NULL); + glCompileShader(shader); + + delete[] sProgram; + + int iCompilationStatus; + glGetShaderiv(shader, GL_COMPILE_STATUS, &iCompilationStatus); + + if (iCompilationStatus == GL_FALSE) + { + char sInfoLog[1024]; + char sFinalMessage[1536]; + int iLogLength; + glGetShaderInfoLog(shader, 1024, &iLogLength, sInfoLog); + sprintf(sFinalMessage, "Error! Shader file %s wasn't compiled! The compiler returned:\n\n%s", file.c_str(), sInfoLog); + MessageBox(NULL, sFinalMessage, "Error", MB_ICONERROR); + return false; + } + this->file = file; + this->type = type; + this->loaded = true; + + return true; +} + +bool CShader::GetLinesFromFile(string sFile, bool bIncludePart, vector* vResult) +{ + FILE* fp = fopen(sFile.c_str(), "rt"); + if (!fp)return false; + + string sDirectory; + int slashIndex = -1; + for (int i = sFile.size() - 1; i >= 0; i--) + { + if (sFile[i] == '\\' || sFile[i] == '/') + { + slashIndex = i; + break; + } + } + + sDirectory = sFile.substr(0, slashIndex + 1); + + // Get all lines from a file + + char sLine[255]; + + bool bInIncludePart = false; + + while (fgets(sLine, 255, fp)) + { + stringstream ss(sLine); + string sFirst; + ss >> sFirst; + if (sFirst == "#include") + { + string sFileName; + ss >> sFileName; + if (sFileName.size() > 0 && sFileName[0] == '\"' && sFileName[sFileName.size() - 1] == '\"') + { + sFileName = sFileName.substr(1, sFileName.size() - 2); + GetLinesFromFile(sDirectory + sFileName, true, vResult); + } + } + else if (sFirst == "#include_part") + bInIncludePart = true; + else if (sFirst == "#definition_part") + bInIncludePart = false; + else if (!bIncludePart || (bIncludePart && bInIncludePart)) + vResult->push_back(sLine); + } + fclose(fp); + + return true; +} + + +bool CShader::isLoaded() +{ + return loaded; +} + +GLuint CShader::getID() +{ + return shader; +} + +string CShader::getFile() +{ + return file; +} + +void CShader::release() +{ + if (!isLoaded()) + return; + + loaded = false; + glDeleteShader(shader); +} + + + +CShaderProgram::CShaderProgram() +{ + linked = false; +} + +bool CShaderProgram::initiate(int n_arg, ...) +{ + create(); + va_list shaders; + va_start(shaders, n_arg); + for (int i = 0; i <= n_arg; i++) + { + if (!addShader(va_arg(shaders, CShader*))) + { + return false; + } + } + va_end(shaders); + if (!link()) + return false; + linked = true; + return true; +} + +bool CShaderProgram::initiate(CShader* vertex, CShader* fragment) +{ + create(); + if (!addShader(vertex) || !addShader(fragment)) + return false; + if (!link()) + return false; + linked = true; + return true; +} + +void CShaderProgram::create() +{ + program = glCreateProgram(); +} + +bool CShaderProgram::addShader(CShader* shader) +{ + if (!shader->isLoaded()) + { + char* errorMsg; + sprintf(errorMsg, "Error! Shader file %s wasn't loaded properly\n", shader->getFile()); + MessageBox(NULL, errorMsg, "Program error", MB_ICONERROR); + return false; + } + + glAttachShader(program, shader->getID()); + + return true; +} + +bool CShaderProgram::link() +{ + glLinkProgram(program); + int status; + glGetProgramiv(program, GL_LINK_STATUS, &status); + linked = status == GL_TRUE; + if (!linked) + { + MessageBox(NULL, "Program cannot be linked", "Program error", MB_ICONERROR); + } + return linked; +} + +void CShaderProgram::release() +{ + if (!linked) + return; + linked = false; + glDeleteProgram(program); +} + +void CShaderProgram::use() +{ + if (linked) + glUseProgram(program); +} + +GLuint CShaderProgram::operator()() +{ + return program; +} + +void CShaderProgram::SetUniform(string sName, float* fValues, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform1fv(iLoc, iCount, fValues); +} + +void CShaderProgram::SetUniform(string sName, const float fValue) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform1fv(iLoc, 1, &fValue); +} + +// Setting vectors + +void CShaderProgram::SetUniform(string sName, glm::vec2* vVectors, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform2fv(iLoc, iCount, (GLfloat*)vVectors); +} + +void CShaderProgram::SetUniform(string sName, const glm::vec2 vVector) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform2fv(iLoc, 1, (GLfloat*)&vVector); +} + +void CShaderProgram::SetUniform(string sName, glm::vec3* vVectors, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform3fv(iLoc, iCount, (GLfloat*)vVectors); +} + +void CShaderProgram::SetUniform(string sName, const glm::vec3 vVector) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform3fv(iLoc, 1, (GLfloat*)&vVector); +} + +void CShaderProgram::SetUniform(string sName, glm::vec4* vVectors, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform4fv(iLoc, iCount, (GLfloat*)vVectors); +} + +void CShaderProgram::SetUniform(string sName, const glm::vec4 vVector) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform4fv(iLoc, 1, (GLfloat*)&vVector); +} + +// Setting 3x3 matrices + +void CShaderProgram::SetUniform(string sName, glm::mat3* mMatrices, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniformMatrix3fv(iLoc, iCount, FALSE, (GLfloat*)mMatrices); +} + +void CShaderProgram::SetUniform(string sName, const glm::mat3 mMatrix) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniformMatrix3fv(iLoc, 1, FALSE, (GLfloat*)&mMatrix); +} + +// Setting 4x4 matrices + +void CShaderProgram::SetUniform(string sName, glm::mat4* mMatrices, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniformMatrix4fv(iLoc, iCount, FALSE, (GLfloat*)mMatrices); +} + +void CShaderProgram::SetUniform(string sName, const glm::mat4 mMatrix) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniformMatrix4fv(iLoc, 1, FALSE, (GLfloat*)&mMatrix); +} + +// Setting integers + +void CShaderProgram::SetUniform(string sName, int* iValues, int iCount) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform1iv(iLoc, iCount, iValues); +} + +void CShaderProgram::SetUniform(string sName, const int iValue) +{ + int iLoc = glGetUniformLocation(program, sName.c_str()); + glUniform1i(iLoc, iValue); +} + +void CShaderProgram::SetModelAndNormalMatrix(string sModelMatrixName, string sNormalMatrixName, glm::mat4 mModelMatrix) +{ + SetUniform(sModelMatrixName, mModelMatrix); + SetUniform(sNormalMatrixName, glm::transpose(glm::inverse(mModelMatrix))); +} + +void CShaderProgram::SetModelAndNormalMatrix(string sModelMatrixName, string sNormalMatrixName, glm::mat4* mModelMatrix) +{ + SetUniform(sModelMatrixName, mModelMatrix); + SetUniform(sNormalMatrixName, glm::transpose(glm::inverse(*mModelMatrix))); +} \ No newline at end of file diff --git a/astria/Shader.h b/astria/Shader.h new file mode 100644 index 0000000..f431ae2 --- /dev/null +++ b/astria/Shader.h @@ -0,0 +1,92 @@ +#ifndef _SHADER_H_ +#define _SHADER_H_ + +#include +#include +#include + +#include +#include + +using namespace std; + +//Shader wrapper class + +class CShader +{ +public: + bool load(string file, int type); + void release(); + + bool GetLinesFromFile(string sFile, bool bIncludePart, vector* vResult); + + bool isLoaded(); + GLuint getID(); + + string getFile(); + + CShader(); + ~CShader(); + +private: + GLuint shader; //ID of shader + string file; + int type; //type of shader (e.g. GL_VERTEX_SHADER, GL_FRAGMENT_SHADER) + bool loaded; //loaded and compiled +}; + +class CShaderProgram +{ +public: + bool initiate(int n_arg, ...); + bool initiate(CShader* vertex, CShader* fragment); + + void create(); + void release(); + + bool addShader(CShader* shader); + bool link(); + + void use(); + + GLuint operator()(); + + GLuint getID(); + + // Setting vectors + void SetUniform(string sName, glm::vec2* vVectors, int iCount = 1); + void SetUniform(string sName, const glm::vec2 vVector); + void SetUniform(string sName, glm::vec3* vVectors, int iCount = 1); + void SetUniform(string sName, const glm::vec3 vVector); + void SetUniform(string sName, glm::vec4* vVectors, int iCount = 1); + void SetUniform(string sName, const glm::vec4 vVector); + + // Setting floats + void SetUniform(string sName, float* fValues, int iCount = 1); + void SetUniform(string sName, const float fValue); + + // Setting 3x3 matrices + void SetUniform(string sName, glm::mat3* mMatrices, int iCount = 1); + void SetUniform(string sName, const glm::mat3 mMatrix); + + // Setting 4x4 matrices + void SetUniform(string sName, glm::mat4* mMatrices, int iCount = 1); + void SetUniform(string sName, const glm::mat4 mMatrix); + + // Setting integers + void SetUniform(string sName, int* iValues, int iCount = 1); + void SetUniform(string sName, const int iValue); + + // Model and normal matrix setting ispretty common + void SetModelAndNormalMatrix(string sModelMatrixName, string sNormalMatrixName, glm::mat4 mModelMatrix); + void SetModelAndNormalMatrix(string sModelMatrixName, string sNormalMatrixName, glm::mat4* mModelMatrix); + + + CShaderProgram(); + +private: + GLuint program; //ID of program + bool linked; //linked and ready to use +}; + +#endif \ No newline at end of file diff --git a/astria/Skybox.cpp b/astria/Skybox.cpp new file mode 100644 index 0000000..6989dd9 --- /dev/null +++ b/astria/Skybox.cpp @@ -0,0 +1,105 @@ +#include "Skybox.h" + +void CSkybox::load(char* front, char* back, char* left, char* right, char* top, char* bottom) +{ + textures[0].load_2D(front); + textures[1].load_2D(back); + textures[2].load_2D(left); + textures[3].load_2D(right); + textures[4].load_2D(top); + textures[5].load_2D(bottom); + + this->front = front; + this->back = back; + this->left = left; + this->right = right; + this->top = top; + this->bottom = bottom; + + for (int i = 0; i<6; i++) + { + textures[i].setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR); + textures[i].setSamplerParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + textures[i].setSamplerParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glGenVertexArrays(1, &VAO); + glBindVertexArray(VAO); + + vboRenderData.create(); + vboRenderData.bind(); + + glm::vec3 SkyBoxVertices[24] = + { + // Front face + glm::vec3(200.0f, 200.0f, 200.0f), glm::vec3(200.0f, -200.0f, 200.0f), glm::vec3(-200.0f, 200.0f, 200.0f), glm::vec3(-200.0f, -200.0f, 200.0f), + // Back face + glm::vec3(-200.0f, 200.0f, -200.0f), glm::vec3(-200.0f, -200.0f, -200.0f), glm::vec3(200.0f, 200.0f, -200.0f), glm::vec3(200.0f, -200.0f, -200.0f), + // Left face + glm::vec3(-200.0f, 200.0f, 200.0f), glm::vec3(-200.0f, -200.0f, 200.0f), glm::vec3(-200.0f, 200.0f, -200.0f), glm::vec3(-200.0f, -200.0f, -200.0f), + // Right face + glm::vec3(200.0f, 200.0f, -200.0f), glm::vec3(200.0f, -200.0f, -200.0f), glm::vec3(200.0f, 200.0f, 200.0f), glm::vec3(200.0f, -200.0f, 200.0f), + // Top face + glm::vec3(-200.0f, 200.0f, -200.0f), glm::vec3(200.0f, 200.0f, -200.0f), glm::vec3(-200.0f, 200.0f, 200.0f), glm::vec3(200.0f, 200.0f, 200.0f), + // Bottom face + glm::vec3(200.0f, -200.0f, -200.0f), glm::vec3(-200.0f, -200.0f, -200.0f), glm::vec3(200.0f, -200.0f, 200.0f), glm::vec3(-200.0f, -200.0f, 200.0f), + }; + /*glm::vec2 SkyBoxTexCoords[4] = + { + glm::vec2(0.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(1.0f, 0.0f) + };*/ + glm::vec2 SkyBoxTexCoords[4] = + { + glm::vec2(0.0f, 0.0f), glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f) + }; + + glm::vec3 SkyBoxNormals[6] = + { + glm::vec3(0.0f, 0.0f, -1.0f), + glm::vec3(0.0f, 0.0f, 1.0f), + glm::vec3(1.0f, 0.0f, 0.0f), + glm::vec3(-1.0f, 0.0f, 0.0f), + glm::vec3(0.0f, -1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f) + }; + + for (int i = 0; i < 24; i++) + { + vboRenderData.addData(&SkyBoxVertices[i], sizeof(glm::vec3)); + vboRenderData.addData(&SkyBoxTexCoords[i % 4], sizeof(glm::vec2)); + vboRenderData.addData(&SkyBoxNormals[i / 4], sizeof(glm::vec3)); + } + + vboRenderData.uploadGPU(GL_STATIC_DRAW); + + // Vertex positions + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec3) + sizeof(glm::vec2), 0); + // Texture coordinates + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec3) + sizeof(glm::vec2), (void*)sizeof(glm::vec3)); + // Normal vectors + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec3) + sizeof(glm::vec2), (void*)(sizeof(glm::vec3) + sizeof(glm::vec2))); +} + +void CSkybox::render() +{ + glDepthMask(0); + glBindVertexArray(VAO); + for (int i = 0; i < 6; i++) + { + textures[i].bind(); + glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4); + } + glDepthMask(1); +} + +void CSkybox::release() +{ + for (int i = 0; i < 6; i++) + { + textures[i].release(); + } + vboRenderData.release(); +} \ No newline at end of file diff --git a/astria/Skybox.h b/astria/Skybox.h new file mode 100644 index 0000000..dea4e6d --- /dev/null +++ b/astria/Skybox.h @@ -0,0 +1,29 @@ +#ifndef _SKYBOX_H_ +#define _SKYBOX_H_ + +#include + +#include "Texture.h" +#include "VBO.h" + +class CSkybox +{ +public: + void load(char* front, char* back, char* left, char* right, char* top, char* bottom); + void render(); + + void release(); + +private: + GLuint VAO; + CVBO vboRenderData; + CTexture textures[6]; + char* front; + char* back; + char* left; + char* right; + char* top; + char* bottom; +}; + +#endif \ No newline at end of file diff --git a/astria/State.cpp b/astria/State.cpp new file mode 100644 index 0000000..47d8466 --- /dev/null +++ b/astria/State.cpp @@ -0,0 +1,29 @@ +#include "State.h" +#include "Agent.h" + +State::State() +{ + +} + +State::~State() +{ + +} + +// ===== Pure virtual functions ===== + +void State::Enter(Agent*) +{ + +} + +void State::Execute(Agent*) +{ + +} + +void State::Exit(Agent*) +{ + +} \ No newline at end of file diff --git a/astria/State.h b/astria/State.h new file mode 100644 index 0000000..a841ae7 --- /dev/null +++ b/astria/State.h @@ -0,0 +1,35 @@ +#ifndef _STATE_H_ +#define _STATE_H_ + +#include "Agent.h" + +class State +{ +public: + State(); + virtual ~State(); + + virtual void Enter(Agent*) = 0; + virtual void Execute(Agent*) = 0; + virtual void Exit(Agent*) = 0; +}; + +class State_Roam : public State +{ +public: + State_Roam(); + void Enter(Agent* agent); + void Execute(Agent* agent); + void Exit(Agent* agent); +}; + +class State_Flee : public State +{ +public: + State_Flee(); + void Enter(Agent* agent); + void Execute(Agent* agent); + void Exit(Agent* agent); +}; + +#endif \ No newline at end of file diff --git a/astria/StaticObj.cpp b/astria/StaticObj.cpp new file mode 100644 index 0000000..ad99795 --- /dev/null +++ b/astria/StaticObj.cpp @@ -0,0 +1,41 @@ +#include "StaticObj.h" + +glm::vec2 vCubeTexCoords[6] = { glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f), glm::vec2(0.0f, 1.0f) }; + +glm::vec3 vGround[6] = +{ + glm::vec3(-1000, 0, -1000), glm::vec3(-1000, 0, 1000), glm::vec3(1000, 0, 1000), glm::vec3(1000, 0, 1000), glm::vec3(1000, 0, -1000), glm::vec3(-1000, 0, -1000) +}; + +int iSphereFaces; + +void CreateStaticSceneObjects(GLuint* VAO, CVBO& vboDest) +{ + vboDest.create(); + glGenVertexArrays(1, VAO); + glBindVertexArray(*VAO); + + vboDest.bind(); + + //Add ground to VBO + for (int i = 0; i < 6; i++) + { + vboDest.addData(&vGround[i], sizeof(glm::vec3)); + glm::vec2 vCoord = vCubeTexCoords[i] * 50.0f; + vboDest.addData(&vCoord, sizeof(glm::vec2)); + glm::vec3 vGroundNormal(0.0f, 1.0f, 0.0f); + vboDest.addData(&vGroundNormal, sizeof(glm::vec3)); + } + + vboDest.uploadGPU(GL_STATIC_DRAW); + + // Vertex positions + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec3) + sizeof(glm::vec2), 0); + // Texture coordinates + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec3) + sizeof(glm::vec2), (void*)sizeof(glm::vec3)); + // Normal vectors + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec3) + sizeof(glm::vec2), (void*)(sizeof(glm::vec3) + sizeof(glm::vec2))); +} \ No newline at end of file diff --git a/astria/StaticObj.h b/astria/StaticObj.h new file mode 100644 index 0000000..6f115df --- /dev/null +++ b/astria/StaticObj.h @@ -0,0 +1,8 @@ +#ifndef _STATIC_OBJ_ +#define _STATIC_OBJ_ + +#include "VBO.h" + +void CreateStaticSceneObjects(GLuint* VAO, CVBO& vboDest); + +#endif \ No newline at end of file diff --git a/astria/Stringify.cpp b/astria/Stringify.cpp new file mode 100644 index 0000000..c92110e --- /dev/null +++ b/astria/Stringify.cpp @@ -0,0 +1,97 @@ +//============================================================================== +#include "Stringify.h" + +//============================================================================== +std::string Stringify::Int(int x) { + std::ostringstream o; + + o << x; + + return o.str(); +} + +//------------------------------------------------------------------------------ +std::string Stringify::Char(char* x) { + std::string o = x; + + return o; +} + +//------------------------------------------------------------------------------ +std::string Stringify::Float(float x) { + std::ostringstream o; + + o << x; + + return o.str(); +} + +//------------------------------------------------------------------------------ +std::string Stringify::Double(double x) { + std::ostringstream o; + + o << x; + + return o.str(); +} + +//============================================================================== +int Stringify::ToInt(const std::string& String) { + if(String == "") return 0; + + int X; + std::stringstream strStream(String); + + strStream >> X; + + return X; +} + +//------------------------------------------------------------------------------ +float Stringify::ToFloat(const std::string& String) { + if(String == "") return 0; + + float X; + std::stringstream strStream(String); + + strStream >> X; + + return X; +} + +//------------------------------------------------------------------------------ +double Stringify::ToDouble(const std::string& String) { + if(String == "") return 0; + + double X; + std::stringstream strStream(String); + + strStream >> X; + + return X; +} + +//============================================================================== +//http://www.infernodevelopment.com/perfect-c-string-explode-split +std::vector Stringify::Explode(std::string str, const std::string& separator) { + std::vector Results; + + int found; + found = str.find_first_of(separator); + while(found != std::string::npos){ + if(found > 0){ + Results.push_back(str.substr(0,found)); + } + + str = str.substr(found+1); + found = str.find_first_of(separator); + } + + if(str.length() > 0){ + Results.push_back(str); + } + + return Results; +} + +//============================================================================== diff --git a/astria/Stringify.h b/astria/Stringify.h new file mode 100644 index 0000000..455a175 --- /dev/null +++ b/astria/Stringify.h @@ -0,0 +1,32 @@ +//============================================================================== +/* + Utility class for converting to and from strings + + 3/18/2014 + SDLTutorials.com + Tim Jones +*/ +//============================================================================== +#ifndef _STRINGIFY_H_ + #define _STRINGIFY_H_ + +#include +#include +#include +#include + +class Stringify { + public: + static std::string Int(int x); + static std::string Char(char* x); + static std::string Float(float x); + static std::string Double(double x); + + static int ToInt(const std::string& String); + static float ToFloat(const std::string& String); + static double ToDouble(const std::string& String); + + static std::vector Explode(std::string str, const std::string& separator); +}; + +#endif diff --git a/astria/Texture.cpp b/astria/Texture.cpp new file mode 100644 index 0000000..cdfb8ce --- /dev/null +++ b/astria/Texture.cpp @@ -0,0 +1,272 @@ +#include "Texture.h" +#include + +std::string GetFileExtension(const std::string& FileName) +{ + if (FileName.find_last_of(".") != std::string::npos) + return FileName.substr(FileName.find_last_of(".") + 1); + return ""; +} + +CTexture::CTexture() +{ + mipmap = false; + file = ""; +} + +CTexture::CTexture(char* file, bool generateMipMap) +{ + load_2D(file, generateMipMap); +} + +bool CTexture::load_2D(char* file, bool generateMipMap) +{ + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + this->mipmap = generateMipMap; + this->file = file; + const char* ext = GetFileExtension(file).c_str(); + if (ext == "dds") + { + return load_DDS(file); + } + else + { + return load_SDL(file); + } +} + + +//Constants for compressed textures +#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII +#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII +#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII +bool CTexture::load_DDS(char* file) +{ + unsigned char header[124]; + + FILE *fp; + + /* try to open the file */ + fp = fopen(file, "rb"); + if (fp == NULL){ + printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", file); getchar(); + return 0; + } + + /* verify the type of file */ + char filecode[4]; + fread(filecode, 1, 4, fp); + if (strncmp(filecode, "DDS ", 4) != 0) { + printf("Wrong extension!\n"); + fclose(fp); + return 0; + } + + /* get the surface desc */ + fread(&header, 124, 1, fp); + + unsigned int height = *(unsigned int*)&(header[8]); + unsigned int width = *(unsigned int*)&(header[12]); + unsigned int linearSize = *(unsigned int*)&(header[16]); + unsigned int mipMapCount = *(unsigned int*)&(header[24]); + unsigned int fourCC = *(unsigned int*)&(header[80]); + + + unsigned char * buffer; + unsigned int bufsize; + /* how big is it going to be including all mipmaps? */ + bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize; + buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char)); + fread(buffer, 1, bufsize, fp); + /* close the file pointer */ + fclose(fp); + + unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4; + unsigned int format; + switch (fourCC) + { + case FOURCC_DXT1: + format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + break; + case FOURCC_DXT3: + format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + case FOURCC_DXT5: + format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + default: + free(buffer); + return 0; + } + + // "Bind" the newly created texture : all future texture functions will modify this texture + glBindTexture(GL_TEXTURE_2D, texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16; + unsigned int offset = 0; + + /* load the mipmaps */ + for (unsigned int level = 0; level < mipMapCount && (width || height); ++level) + { + unsigned int size = ((width + 3) / 4)*((height + 3) / 4)*blockSize; + glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, + 0, size, buffer + offset); + + offset += size; + width /= 2; + height /= 2; + + // Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter. + if (width < 1) width = 1; + if (height < 1) height = 1; + + } + + free(buffer); + return true; +} + +bool CTexture::load_SDL(char* file) +{ + SDL_Surface* Surf_Load = IMG_Load(file); + + if (Surf_Load == NULL) + { + char* errorMsg; + sprintf(errorMsg, "Error loading %s!\nError message: %s\n", file, IMG_GetError()); + MessageBox(NULL, errorMsg, "Texture loading error", MB_ICONERROR); + return false; + } + + glGenTextures(1, &texture); + + glBindTexture(GL_TEXTURE_2D, texture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Surf_Load->w, Surf_Load->h, 0, GL_RGB, GL_UNSIGNED_BYTE, Surf_Load->pixels); + + if (mipmap){ + glGenerateMipmap(GL_TEXTURE_2D); //Generate mipmaps + } + + SDL_FreeSurface(Surf_Load); + + return true; +} + +void CTexture::createEmpty(int width, int height, GLenum format) +{ + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + if (format == GL_RGBA || format == GL_BGRA) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + // We must handle this because of internal format parameter + else if (format == GL_RGB || format == GL_BGR) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + else + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + + glGenSamplers(1, &sampler); +} + +void CTexture::createFromData(BYTE* data, int width, int height, int BPP, GLenum format, bool generateMipMap) +{ + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + if (format == GL_RGBA || format == GL_BGRA) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + // We must handle this because of internal format parameter + else if (format == GL_RGB || format == GL_BGR) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + else + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + if (generateMipMap) + glGenerateMipmap(GL_TEXTURE_2D); + glGenSamplers(1, &sampler); + + this->file = ""; + this->mipmap = generateMipMap; + this->width = width; + this->height = height; + this->BPP = BPP; +} + +void CTexture::setSamplerParameter(GLenum parameter, GLenum value) +{ + glSamplerParameteri(sampler, parameter, value); +} + +void CTexture::setFiltering(int magnification, int minification) +{ + glBindSampler(0, sampler); + + // Set magnification filter + if (magnification == TEXTURE_FILTER_MAG_NEAREST) + glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else if (magnification == TEXTURE_FILTER_MAG_BILINEAR) + glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Set minification filter + if (minification == TEXTURE_FILTER_MIN_NEAREST) + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + else if (minification == TEXTURE_FILTER_MIN_BILINEAR) + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + else if (minification == TEXTURE_FILTER_MIN_NEAREST_MIPMAP) + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + else if (minification == TEXTURE_FILTER_MIN_BILINEAR_MIPMAP) + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + else if (minification == TEXTURE_FILTER_MIN_TRILINEAR) + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + + minification = minification; + magnification = magnification; +} + +void CTexture::bind(int textureUnit) +{ + glActiveTexture(GL_TEXTURE0 + textureUnit); + glBindTexture(GL_TEXTURE_2D, texture); + glBindSampler(texture, sampler); +} + +void CTexture::release() +{ + glDeleteSamplers(1, &sampler); + glDeleteTextures(1, &texture); +} + +int CTexture::getMagnificationFilter() +{ + return magnification; +} + +int CTexture::getMinificationFilter() +{ + return minification; +} + +int CTexture::getWidth() +{ + return width; +} + +int CTexture::getHeight() +{ + return height; +} + +int CTexture::getBPP() +{ + return BPP; +} + +GLuint CTexture::getID() +{ + return texture; +} + +char* CTexture::getFile() +{ + return file; +} \ No newline at end of file diff --git a/astria/Texture.h b/astria/Texture.h new file mode 100644 index 0000000..43d35f3 --- /dev/null +++ b/astria/Texture.h @@ -0,0 +1,64 @@ +#ifndef _TEXTURE_H_ +#define _TEXTURE_H_ + +#include +#include +#include + +enum ETextureFiltering +{ + TEXTURE_FILTER_MAG_NEAREST = 0, // Nearest criterion for magnification + TEXTURE_FILTER_MAG_BILINEAR, // Bilinear criterion for magnification + TEXTURE_FILTER_MIN_NEAREST, // Nearest criterion for minification + TEXTURE_FILTER_MIN_BILINEAR, // Bilinear criterion for minification + TEXTURE_FILTER_MIN_NEAREST_MIPMAP, // Nearest criterion for minification, but on closest mipmap + TEXTURE_FILTER_MIN_BILINEAR_MIPMAP, // Bilinear criterion for minification, but on closest mipmap + TEXTURE_FILTER_MIN_TRILINEAR, // Bilinear criterion for minification on two closest mipmaps, then averaged +}; + +class CTexture +{ +public: + CTexture(); + CTexture(char* file, bool generateMipMap = false); + + bool load_2D(char* file, bool generateMipMap = false); + void createEmpty(int width, int height, GLenum format); + void createFromData(BYTE* data, int width, int height, int BPP, GLenum format, bool generateMipMap = false); + void release(); + + bool reload(); + + void setFiltering(int magnification, int minification); + void setSamplerParameter(GLenum parament, GLenum value); + + int getMinificationFilter(); + int getMagnificationFilter(); + + int getWidth(); + int getHeight(); + int getBPP(); + + char* getFile(); + + void bind(int textureUnit = 0); + + GLuint getID(); + GLuint operator()(); + +private: + bool load_SDL(char* file); + bool load_DDS(char* file); + +private: + char* file; + GLuint texture; + GLuint sampler; + int width, height, BPP; + bool mipmap; + + int minification; + int magnification; +}; + +#endif \ No newline at end of file diff --git a/astria/VBO.cpp b/astria/VBO.cpp new file mode 100644 index 0000000..929901e --- /dev/null +++ b/astria/VBO.cpp @@ -0,0 +1,78 @@ +#include "VBO.h" + +CVBO::CVBO() +{ + dataUploaded = false; + buffer = 0; +} + +void CVBO::create(int size) +{ + glGenBuffers(1, &buffer); + data.reserve(size); + this->size = size; + currentSize = 0; +} + +void CVBO::release() +{ + glDeleteBuffers(1, &buffer); + dataUploaded = false; + data.clear(); +} + +void* CVBO::mapBuffer(int hint) +{ + if (!dataUploaded) + return NULL; + void* ptrRes = glMapBuffer(type, hint); +} + +void* CVBO::mapSubBuffer(int hint, GLuint offset, GLuint length) +{ + if (!dataUploaded) + return NULL; + void* ptrRes = glMapBufferRange(type, offset, length, hint); + return ptrRes; +} + +void CVBO::unmapBuffer() +{ + glUnmapBuffer(type); +} + +void CVBO::bind(int type) +{ + this->type = type; + glBindBuffer(type, buffer); +} + +void CVBO::uploadGPU(int hint) +{ + glBufferData(type, data.size(), &data[0], hint); + dataUploaded = true; + data.clear(); +} + +void CVBO::addData(void* ptrData, GLuint size) +{ + data.insert(data.end(), (BYTE*)ptrData, (BYTE*)ptrData + size); + currentSize += size; +} + +void* CVBO::getDataPointer() +{ + if (dataUploaded) + return NULL; + return (void*)data[0]; +} + +GLuint CVBO::getID() +{ + return buffer; +} + +int CVBO::getCurrentSize() +{ + return currentSize; +} \ No newline at end of file diff --git a/astria/VBO.h b/astria/VBO.h new file mode 100644 index 0000000..b87e510 --- /dev/null +++ b/astria/VBO.h @@ -0,0 +1,41 @@ +#ifndef _VBO_H_ +#define _VBO_H_ + +#include +#include +#include +#include + +class CVBO +{ +public: + CVBO(); + + void create(int size = 0); + void release(); + + void* mapBuffer(int hint); + void* mapSubBuffer(int hint, GLuint offset, GLuint length); + void unmapBuffer(); + + void bind(int type = GL_ARRAY_BUFFER); + void uploadGPU(int hint); + + void addData(void* ptrData, GLuint size); + + void* getDataPointer(); + GLuint getID(); + + int getCurrentSize(); + +private: + GLuint buffer; + int size; + int currentSize; + int type; + std::vector data; + + bool dataUploaded; +}; + +#endif \ No newline at end of file diff --git a/astria/astria.vcxproj b/astria/astria.vcxproj new file mode 100644 index 0000000..8de81db --- /dev/null +++ b/astria/astria.vcxproj @@ -0,0 +1,117 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {AA160014-3EA4-4114-B955-031B22CC7A6A} + astria + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/astria/astria.vcxproj.filters b/astria/astria.vcxproj.filters new file mode 100644 index 0000000..aee59c8 --- /dev/null +++ b/astria/astria.vcxproj.filters @@ -0,0 +1,174 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {731f55e8-d50a-4743-bca6-7bb88b86d19e} + + + {565c6273-ed13-4ba7-be73-7e73b3743e3d} + + + {095a9e94-8c41-41fc-aac1-05e8bc3d0173} + + + {28fbec19-8d4f-44e9-b0c0-3385e485540d} + + + {d434d2c6-66b5-4479-9c6e-a5d0684c9652} + + + {de154463-4981-4d4c-b947-f3126ebded77} + + + {ffecb7e9-9cd0-4c80-9540-edd24182b9bc} + + + + + Source Files\OpenGL + + + Source Files\OpenGL + + + Source Files\OpenGL + + + Source Files\Main + + + Source Files\Main + + + Source Files\Main + + + Source Files\Main + + + Source Files\Main + + + Source Files\OpenGL + + + Source Files\AI + + + Source Files\AI + + + Source Files\common + + + Source Files\common + + + Source Files\common + + + Source Files\common + + + Source Files\common + + + Source Files\AI + + + Source Files\common + + + Source Files\AI + + + Source Files\OpenGL + + + Source Files\OpenGL + + + Source Files\Main + + + Source Files\common + + + + + Header Files\OpenGL + + + Header Files\OpenGL + + + Header Files\OpenGL + + + Header Files\OpenGL + + + Header Files\OpenGL + + + Header Files\common + + + Header Files\common + + + Header Files\common + + + Header Files\common + + + Header Files\common + + + Header Files\OpenGL + + + Header Files\OpenGL + + + Header Files\common + + + Header Files\AI + + + Header Files\AI + + + Header Files + + + Header Files\common + + + Header Files + + + Header Files\AI + + + Header Files\AI + + + Header Files\common + + + \ No newline at end of file diff --git a/astria/utils.h b/astria/utils.h new file mode 100644 index 0000000..1932b43 --- /dev/null +++ b/astria/utils.h @@ -0,0 +1,25 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include +#include +#include "Params.h" + +//returns a random integer between x and y +inline int RandInt(int x, int y) { return rand() % (y - x + 1) + x; } + +//returns a random float between zero and 1 +inline double RandFloat() { return (rand()) / (RAND_MAX + 1.0); } + +//returns a random bool +inline bool RandBool(){ if (RandInt(0, 1)) return true; else return false;} + +//returns a random float in the range -1 < n < 1 +inline double RandNormal() { return RandFloat() - RandFloat(); } + +//Clamp first argument between 2nd and 3rd arguments +inline void Clamp(double &arg, double min, double max) { arg = arg <= min ? min : (arg >= max ? max : arg); } + +inline double ToDeg(double radian) { return radian * 180 / CParams::Pi; } + +#endif \ No newline at end of file