diff options
Diffstat (limited to 'src')
71 files changed, 3109 insertions, 0 deletions
diff --git a/src/libjin/Audio/Audio.cpp b/src/libjin/Audio/Audio.cpp new file mode 100644 index 0000000..363bf4d --- /dev/null +++ b/src/libjin/Audio/Audio.cpp @@ -0,0 +1,15 @@ +#include "../modules.h" +#if JIN_MODULES_AUDIO + +#include <SDL2/SDL.h> +#include "audio.h" + +namespace jin +{ +namespace audio +{ + +} +} + +#endif // JIN_MODULES_AUDIO
\ No newline at end of file diff --git a/src/libjin/Audio/Audio.h b/src/libjin/Audio/Audio.h new file mode 100644 index 0000000..faec4db --- /dev/null +++ b/src/libjin/Audio/Audio.h @@ -0,0 +1,46 @@ +#ifndef __JIN_AUDIO_H +#define __JIN_AUDIO_H +#include "../modules.h" +#if JIN_MODULES_AUDIO + +#include <SDL2/SDL.h> + +#include "../utils/macros.h" +#include "../common/subsystem.h" + +namespace jin +{ +namespace audio +{ + class Source; + + template<class SubAudioSystem> + class AudioSystem : public Subsystem<SubAudioSystem> + { + + public: + + virtual void play() = 0; + virtual void stop() = 0; + virtual bool pause() = 0; + virtual bool pause(Source* source) = 0; + virtual bool resume() = 0; + virtual bool resume(Source* source) = 0; + virtual void rewind() = 0; + virtual void setVolume(float volume) = 0; + virtual float getVolume() = 0; + + protected: + + AudioSystem() {}; + virtual ~AudioSystem() {}; + + SINGLETON(AudioSystem); + + }; + +} +} + +#endif // JIN_MODULES_AUDIO +#endif
\ No newline at end of file diff --git a/src/libjin/Audio/OpenAL/Audio.cpp b/src/libjin/Audio/OpenAL/Audio.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Audio/OpenAL/Audio.cpp diff --git a/src/libjin/Audio/OpenAL/Audio.h b/src/libjin/Audio/OpenAL/Audio.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Audio/OpenAL/Audio.h diff --git a/src/libjin/Audio/OpenAL/Source.cpp b/src/libjin/Audio/OpenAL/Source.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Audio/OpenAL/Source.cpp diff --git a/src/libjin/Audio/OpenAL/Source.h b/src/libjin/Audio/OpenAL/Source.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Audio/OpenAL/Source.h diff --git a/src/libjin/Audio/SDL/Audio.cpp b/src/libjin/Audio/SDL/Audio.cpp new file mode 100644 index 0000000..47d8cf8 --- /dev/null +++ b/src/libjin/Audio/SDL/Audio.cpp @@ -0,0 +1,121 @@ +#include "../../modules.h" +#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO + +#include <iostream> +#include "audio.h" +#include "source.h" +#include "../../math/math.h" +#include "../../utils/log.h" + +namespace jin +{ +namespace audio +{ + + /* עcallbackƵ̵߳ */ + static void defaultCallback(void *userdata, Uint8 *stream, int size) + { + static SDLAudio* audio = static_cast<SDLAudio*>(userdata); + audio->lock(); + audio->processCommands(); + audio->processSources(stream, size); + audio->unlock(); + } + + onlyonce bool SDLAudio::initSystem(const SettingBase* s) + { + Loghelper::log(Loglevel::LV_INFO, "Init Audio System"); + + if (SDL_Init(SDL_INIT_AUDIO) < 0) + return false; + SDL_AudioSpec spec; + Setting* setting = (Setting*)s; + if (setting == nullptr) + return false; + + unsigned int samplerate = setting->samplerate; + unsigned int samples = clamp(setting->samples, 1, setting->samplerate); + + spec.freq = samplerate; // ÿsample,õ 11025, 22050, 44100 and 48000 Hz. + spec.format = AUDIO_S16SYS; // signed 16-bit samples in native byte order + spec.channels = SDLAUDIO_CHANNELS; // + spec.samples = samples; // ÿβʱһã=setting->samplerateÿֻ1 + spec.userdata = this; + spec.callback = defaultCallback; + + audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0); + if (audioDevice == 0) + return false; + /* start audio */ + SDL_PauseAudioDevice(audioDevice, 0); + return true; + } + + onlyonce void SDLAudio::quitSystem() + { + SDL_CloseAudio(); + } + + void SDLAudio::lock() + { + SDL_LockAudioDevice(audioDevice); + } + + void SDLAudio::unlock() + { + SDL_UnlockAudioDevice(audioDevice); + } + + void SDLAudio::processCommands() + { + SDLSourceManager::get()->processCommands(); + } + + void SDLAudio::processSources(void* buffer, size_t len) + { + SDLSourceManager::get()->processSources(buffer, len); + } + + void SDLAudio::play() {} + + void SDLAudio::stop() {} + + bool SDLAudio::pause() + { + return false; + } + + bool SDLAudio::pause(Source* source) + { + return false; + } + + bool SDLAudio::resume() + { + return false; + } + + bool SDLAudio::resume(Source* source) + { + return false; + } + + void SDLAudio::rewind() + { + + } + + void SDLAudio::setVolume(float volume) + { + + } + + float SDLAudio::getVolume() + { + return 0.f; + } + +} +} + +#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
\ No newline at end of file diff --git a/src/libjin/Audio/SDL/Audio.h b/src/libjin/Audio/SDL/Audio.h new file mode 100644 index 0000000..6da6605 --- /dev/null +++ b/src/libjin/Audio/SDL/Audio.h @@ -0,0 +1,68 @@ +#ifndef __JIN_AUDIO_SDL_H +#define __JIN_AUDIO_SDL_H +#include "../../modules.h" +#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO + +#include <vector> +#include "../audio.h" + +namespace jin +{ +namespace audio +{ + +#define SDLAUDIO_BITDEPTH 16 +#define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3) +#define SDLAUDIO_CHANNELS 2 + + class SDLAudio : public AudioSystem<SDLAudio> + { + + public: + + struct Setting : SettingBase + { + public: + int samplerate; // Ƶ + int samples; // sample<=samplerate + }; + + /* IAudio interface */ + void play() override; + void stop() override; + bool pause() override; + bool pause(Source* source) override; + bool resume() override; + bool resume(Source* source) override; + void rewind() override; + void setVolume(float volume) override; + float getVolume() override; + + /* process functions*/ + void processCommands(); + void processSources(void* buffer, size_t len); + + void lock(); + void unlock(); + + private: + + SDLAudio() {}; + ~SDLAudio() {}; + + SINGLETON(SDLAudio); + + onlyonce bool initSystem(const SettingBase* setting) override; + onlyonce void quitSystem() override; + + unsigned int audioDevice; + + }; + + typedef SDLAudio::Setting SDLAudioSetting; + +} +} + +#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO +#endif
\ No newline at end of file diff --git a/src/libjin/Audio/SDL/Source.cpp b/src/libjin/Audio/SDL/Source.cpp new file mode 100644 index 0000000..0eedbba --- /dev/null +++ b/src/libjin/Audio/SDL/Source.cpp @@ -0,0 +1,399 @@ +#include "../../modules.h" +#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO + +#include <exception> +#include <fstream> + +#include "../../math/math.h" +#include "../../utils/macros.h" +#include "source.h" +#include "3rdparty/wav/wav.h" +#define STB_VORBIS_HEADER_ONLY +#include "3rdparty/stb/stb_vorbis.c" + +#include "audio.h" + +namespace jin +{ +namespace audio +{ + +#define BITS 8 + + typedef struct SDLSourceCommand + { + typedef enum Action + { + Nothing = 0, + Play, + Stop, + Pause, + Resume, + Rewind, + SetVolume, + SetLoop, + SetRate, + }; + Action action; + union { + int _integer; + float _float; + bool _boolean; + const char* _string; + } parameter; + + SDLSource* source; + }; + + typedef enum CHANNEL + { + MONO = 1, // + STEREO = 2, // + }; + + typedef MASK enum STATUS + { + PLAYING = 1, + PAUSED = 2, + STOPPED = 4 + }; + +#define Command SDLSourceCommand +#define Action Command::Action +#define Manager SDLSourceManager + + shared std::queue<Command*> Manager::commands; + shared std::stack<Command*> Manager::commandsPool; + shared std::vector<SDLSource*> Manager::sources; + shared Manager* Manager::manager = nullptr; + + SDLSource* SDLSource::createSource(const char* file) + { + std::ifstream fs; + fs.open(file, std::ios::binary); + if (!fs.is_open()) + { + fs.close(); + return nullptr; + } + fs.seekg(0,std::ios::end); + int size = fs.tellg(); + fs.seekg(0, std::ios::beg); + char* buffer = (char*)malloc(size); + memset(buffer, 0, size); + fs.read(buffer, size); + fs.close(); + SDLSource* source = createSource(buffer, size); + free(buffer); + return source; + } + + SDLSource* SDLSource::createSource(void* mem, size_t size) + { + if (mem == nullptr) + return nullptr; + SDLSource* source = new SDLSource(); + try + { + SourceType format = getType(mem, size); + switch (format) + { + case OGG: source->decode_ogg(mem, size); break; + case WAV: source->decode_wav(mem, size); break; + } + } + catch (SourceException& exp) + { + delete source; + return nullptr; + }; + return source; + } + + SDLSource::SDLSource() + { + memset(&status, 0, sizeof(status)); + memset(&raw, 0, sizeof(raw)); + } + + SDLSource::~SDLSource() + { + delete raw.data; + raw.end = 0; + raw.data = 0; + } + + void SDLSource::decode_wav(void* mem, int size) + { + wav_t wav; + if (wav_read(&wav, mem, size) == 0) + { + raw.data = wav.data; + raw.length = wav.length * wav.bitdepth / 8; + raw.end = (char*)raw.data + raw.length; + raw.samplerate = wav.samplerate; + raw.bitdepth = wav.bitdepth; + raw.samples = raw.length / (wav.bitdepth / 8.f) / wav.channels; + raw.channels = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO); + } + else + throw SourceException(); + } + + void SDLSource::decode_ogg(void* _mem, int size) + { + unsigned char* mem = (unsigned char*)_mem; + int channels; + int samplerate; + short* data = (short*)raw.data; + int samples = stb_vorbis_decode_memory( + mem, + size, + &channels, + &samplerate, + &data + ); + const int bitdepth = sizeof(short) * BITS; + raw.channels = channels; + raw.samplerate = samplerate; + raw.data = data; + raw.samples = samples; + raw.length = samples * channels * sizeof(short); + raw.bitdepth = bitdepth; + raw.end = (char*)data + raw.length; + } + +#define ActionNone(T)\ +do{\ +Command* cmd = Manager::get()->getCommand();\ +cmd->action = Action::T; \ +cmd->source = this; \ +Manager::get()->pushCommand(cmd); \ +} while (0) + +#define ActionArg(T, ARGT, ARG)\ +do{\ +Command* cmd = Manager::get()->getCommand();\ +cmd->action = Action::T; \ +cmd->parameter.ARGT = ARG; \ +cmd->source = this; \ +Manager::get()->pushCommand(cmd); \ +}while(0) + +#define ActionInt(T, INT) ActionArg(T, _integer, INT) +#define ActionFloat(T, FLT) ActionArg(T, _float, FLT) +#define ActionString(T, STR) ActionArg(T, _string, STR) +#define ActionBool(T, BOL) ActionArg(T, _boolean, BOL) + + void SDLSource::play() + { + ActionNone(Play); + } + + void SDLSource::stop() + { + ActionNone(Stop); + } + + void SDLSource::pause() + { + ActionNone(Pause); + } + + void SDLSource::resume() + { + ActionNone(Resume); + } + + void SDLSource::rewind() + { + ActionNone(Rewind); + } + + inline bool SDLSource::isStopped() const + { + return is(STOPPED); + } + + bool SDLSource::isPaused() const + { + return is(PAUSED); + } + + void SDLSource::setPitch(float pitch) + { + } + + void SDLSource::setVolume(float volume) + { + ActionFloat(SetVolume, volume); + } + + bool SDLSource::setLoop(bool loop) + { + ActionBool(SetLoop, loop); + return false; + } + + void SDLSource::setRate(float rate) + { + ActionFloat(SetRate, rate); + } + + inline void SDLSource::handle( + SDLSourceManager* manager, + SDLSourceCommand* cmd + ) + { + switch (cmd->action) + { + case Command::Action::Play: + manager->removeSource(this); + manager->pushSource(this); + status.state = PLAYING; + status.pos = 0; // rewind + break; + case Command::Action::Stop: + manager->removeSource(this); + status.state = STOPPED; + status.pos = 0; // rewind + break; + case Command::Action::Pause: + manager->removeSource(this); + status.state = PAUSED; + break; + case Command::Action::Resume: + manager->removeSource(this); + manager->pushSource(this); + status.state = PLAYING; + break; + case Command::Action::Rewind: + status.state = PLAYING; + status.pos = 0; + break; + case Command::Action::SetVolume: + //float cmd->parameter._float; + break; + case Command::Action::SetLoop: + status.loop = cmd->parameter._boolean; + break; + } + } + + inline void SDLSource::process(void* buf, size_t size) + { + short* buffer = (short*)buf; // AUDIO_S16SYS + unsigned int samples = size / SDLAUDIO_BYTEDEPTH; + short* sample; + short origin; + + const char bitdepth = raw.bitdepth; + const char channles = raw.channels; + + int pos = status.pos; + int pitch = status.pitch; + int state = status.state; + bool loop = status.loop; + int volume = status.volume; + short* clip16 = nullptr; + char* clip8 = nullptr; + int clip = 0; + + if (bitdepth == 8) + clip8 = (char*)raw.data; + else if (bitdepth == 16) + clip16 = (short*)raw.data; + + for (int i = 0; i < samples; i+=2 /*˫*/) + { + /* Ƶļsampleᱻ */ + sample = buffer + i * SDLAUDIO_BYTEDEPTH; + origin = *sample; + if (bitdepth == 8) + { + clip = *clip8; + } + else if (bitdepth == 16) + clip = *clip16; + + } + } + + Manager* Manager::get() + { + return (manager == nullptr ? manager = new Manager() : manager); + } + + shared void Manager::processCommands() + { + Command* cmd = nullptr; + SDLSource* source = nullptr; + while (!commands.empty()) + { + cmd = commands.front(); + if (cmd != nullptr) + { + source = cmd->source; + if (source != nullptr) + source->handle(manager, cmd); + } + commands.pop(); + } + } + + /* AUDIO_S16SYS[size>>1] buffer */ + shared void Manager::processSources(void* buf, size_t size) + { + /* clear render buffer */ + memset(buf, 0, size); + SDLSource* src = nullptr; + std::vector<SDLSource*>::iterator it = sources.begin(); + for (; it != sources.end();) + { + src = *it; + if (src != nullptr) + src->process(buf, size); + ++it; + } + } + + shared void Manager::removeSource(SDLSource* source) + { + std::vector<SDLSource*>::iterator it = sources.begin(); + for (it = sources.begin(); it != sources.end(); ) + { + if (*it == source) + { + it = sources.erase(it); + return; + } + ++it; + } + } + + shared void Manager::pushSource(SDLSource* source) + { + if(source != nullptr) + sources.push_back(source); + } + + shared void Manager::pushCommand(SDLSourceCommand* cmd) + { + commands.push(cmd); + } + + shared Command* Manager::getCommand() + { + if (!commandsPool.empty()) + { + Command* cmd = commandsPool.top(); + commandsPool.pop(); + return cmd; + } + return new Command(); + } + +} +} + +#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
\ No newline at end of file diff --git a/src/libjin/Audio/SDL/Source.h b/src/libjin/Audio/SDL/Source.h new file mode 100644 index 0000000..38f7ec4 --- /dev/null +++ b/src/libjin/Audio/SDL/Source.h @@ -0,0 +1,116 @@ +#ifndef __JIN_SOURCE_SDL_H +#define __JIN_SOURCE_SDL_H +#include "../../modules.h" +#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO + +#include <vector> +#include <queue> +#include <stack> +#include <exception> + +#include "../source.h" + +namespace jin +{ +namespace audio +{ + + typedef struct SDLSourceCommand; + class SDLSourceManager; + + class SDLSource : public Source + { + + public: + + ~SDLSource(); + + static SDLSource* createSource(const char* file); + static SDLSource* createSource(void* mem, size_t size); + + /* ISource interface */ + void play() override; + void stop() override; + void pause() override; + void resume() override; + void rewind() override; + bool isStopped() const override; + bool isPaused() const override; + void setPitch(float pitch) override; + // Ͻ + void setVolume(float volume) override; + bool setLoop(bool loop) override; + void setRate(float rate) override; + + inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd); + inline void process(void* buffer, size_t size); + + private: + + SDLSource(); + + void decode_wav(void* mem, int size); + void decode_ogg(void* mem, int size); + + inline bool is(int state) const { return (status.state & state) == state; } + + struct + { + const void* data; // Ƶ + int length; // dataֽڳ + const void* end; // dataβ = (unsigned char*)data + size + int samplerate; // Ƶ + unsigned char bitdepth; // ÿsampleıس + int samples; // sample = size / (bitdepth / 8) + unsigned char channels; // channel1(mono)2(stereo) + } raw; + + /* Procedure controller variable */ + struct + { + int pos; // ǰŵsample + int pitch; // pitch + int state; // ǰ״̬ + bool loop; // loop or not + int volume; // + } status; + + }; + + class SDLSourceManager + { + + public: + + static SDLSourceManager* get(); + + /* Process function */ + static void processCommands(); + static void processSources(void* buffer, size_t size); + + static void removeSource(SDLSource* source); + static void pushSource(SDLSource* source); + static SDLSourceCommand* getCommand(); + static void pushCommand(SDLSourceCommand* cmd); + + static SDLSourceManager* manager; + + static std::queue<SDLSourceCommand*> commands; + static std::stack<SDLSourceCommand*> commandsPool; + static std::vector<SDLSource*> sources; // processing sources + + }; + + class SourceException : public std::exception + { + const char * what() const throw () + { + return "Load Source Exception"; + } + }; + +} +} + +#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO +#endif
\ No newline at end of file diff --git a/src/libjin/Audio/Source.cpp b/src/libjin/Audio/Source.cpp new file mode 100644 index 0000000..ceb882d --- /dev/null +++ b/src/libjin/Audio/Source.cpp @@ -0,0 +1,28 @@ +#include "../modules.h" +#if JIN_MODULES_AUDIO + +#include <cstring> +#include "source.h" + +namespace jin +{ +namespace audio +{ + + static int check_header(const void *data, int size, char *str, int offset) { + int len = strlen(str); + return (size >= offset + len) && !memcmp((char*)data + offset, str, len); + } + + SourceType Source::getType(const void* mem, int size) + { + if(check_header(mem, size, "WAVE", 8)) + return SourceType::WAV; + if(check_header(mem, size, "OggS", 0)) + return SourceType::OGG; + return SourceType::INVALID; + } + +} +} +#endif // JIN_MODULES_AUDIO
\ No newline at end of file diff --git a/src/libjin/Audio/Source.h b/src/libjin/Audio/Source.h new file mode 100644 index 0000000..5b9c12b --- /dev/null +++ b/src/libjin/Audio/Source.h @@ -0,0 +1,51 @@ +#ifndef __JIN_AUDIO_SOURCE_H +#define __JIN_AUDIO_SOURCE_H +#include "../modules.h" +#if JIN_MODULES_AUDIO + +#include <SDL2/SDL.h> + +namespace jin +{ +namespace audio +{ + + enum SourceType + { + INVALID = 0, + WAV, + OGG, + }; + + class Source + { + + public: + + Source() {}; + virtual ~Source() {}; + + /* interface */ + virtual void play() = 0; + virtual void stop() = 0; + virtual void pause() = 0; + virtual void resume() = 0; + virtual void rewind() = 0; + virtual bool isStopped() const = 0; + virtual bool isPaused() const = 0; + virtual void setPitch(float pitch) = 0; + virtual void setVolume(float volume) = 0; + virtual bool setLoop(bool loop) = 0; + virtual void setRate(float rate) = 0; + + protected: + + static SourceType getType(const void* mem, int size); + + }; + +} +} + +#endif // JIN_MODULES_AUDIO +#endif
\ No newline at end of file diff --git a/src/libjin/Common/Data.h b/src/libjin/Common/Data.h new file mode 100644 index 0000000..6f1c504 --- /dev/null +++ b/src/libjin/Common/Data.h @@ -0,0 +1,15 @@ +#ifndef __JIN_COMMON_DATA_H +#define __JIN_COMMON_DATA_H + +namespace jin +{ + + struct Buffer + { + unsigned int len; + char data[0]; + }; + +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Common/Singleton.h b/src/libjin/Common/Singleton.h new file mode 100644 index 0000000..a6c7d6d --- /dev/null +++ b/src/libjin/Common/Singleton.h @@ -0,0 +1,38 @@ +#ifndef __JIN_SINGLETON_H +#define __JIN_SINGLETON_H + +namespace jin +{ + template<class T> + class Singleton + { + public: + static T* get() + { + if (_instance == nullptr) + _instance = new T; + return _instance; + } + static void destroy() + { + delete _instance; + _instance = nullptr; + } + protected: + Singleton() {}; + virtual ~Singleton() {}; + private: + Singleton(const Singleton&); + Singleton& operator = (const Singleton&); + + static T* _instance; + }; + + template<class T> T* Singleton<T>::_instance = nullptr; + +#define SINGLETON(T) \ + friend Singleton<T> + +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Common/Subsystem.h b/src/libjin/Common/Subsystem.h new file mode 100644 index 0000000..35563da --- /dev/null +++ b/src/libjin/Common/Subsystem.h @@ -0,0 +1,42 @@ +#ifndef __JIN_COMMON_SUBSYSTEM_H +#define __JIN_COMMON_SUBSYSTEM_H + +#include "singleton.h" +#include "../utils/macros.h" + +namespace jin +{ + + template<class System> + class Subsystem : public Singleton<System> + { + public: + struct Setting {}; + typedef Setting SettingBase; + + void init(const SettingBase* setting) + { + CALLONCE(initSystem(setting)); + } + + void quit() + { + CALLONCE(quitSystem()); + destroy(); + } + + protected: + + Subsystem() {}; + virtual ~Subsystem() {}; + + SINGLETON(System); + + virtual onlyonce bool initSystem(const Setting* setting) = 0; + virtual onlyonce void quitSystem() = 0; + + }; + +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Core/Core.h b/src/libjin/Core/Core.h new file mode 100644 index 0000000..dd902b4 --- /dev/null +++ b/src/libjin/Core/Core.h @@ -0,0 +1,6 @@ +#ifndef __JIN_CORE_H +#define __JIN_CORE_H + +#include "game.h" + +#endif
\ No newline at end of file diff --git a/src/libjin/Core/Game.cpp b/src/libjin/Core/Game.cpp new file mode 100644 index 0000000..5c2e69b --- /dev/null +++ b/src/libjin/Core/Game.cpp @@ -0,0 +1,12 @@ +#include "game.h" + +namespace jin +{ +namespace core +{ + + Game::Game() :run(true) {}; + +} +} + diff --git a/src/libjin/Core/Game.h b/src/libjin/Core/Game.h new file mode 100644 index 0000000..e155607 --- /dev/null +++ b/src/libjin/Core/Game.h @@ -0,0 +1,59 @@ +#ifndef __JIN_CORE_GAME_H +#define __JIN_CORE_GAME_H + +#include <SDL2/SDL.h> + +#include "../common/singleton.h" +#include "../utils/macros.h" + +namespace jin +{ +namespace core +{ + class Game : public Singleton<Game> + { + public: + + struct Setting + { + + }; + + inline void quit() // quit game loop + { + CALLONCE(_quit()); + } + + inline bool running() + { + return run; + } + + inline void exit() // exit game + { + CALLONCE(_exit()); + } + + private: + + Game(); + ~Game() {}; + + SINGLETON(Game); + + bool run; + + inline void _exit() + { + SDL_Quit(); + } + + inline void _quit() + { + run = false; + } + }; +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Core/Thread.cpp b/src/libjin/Core/Thread.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Core/Thread.cpp diff --git a/src/libjin/Core/Thread.h b/src/libjin/Core/Thread.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/libjin/Core/Thread.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/libjin/Core/Timer.cpp b/src/libjin/Core/Timer.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Core/Timer.cpp diff --git a/src/libjin/Core/Timer.h b/src/libjin/Core/Timer.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/libjin/Core/Timer.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/libjin/Debug/Debug.h b/src/libjin/Debug/Debug.h new file mode 100644 index 0000000..9fa9fe1 --- /dev/null +++ b/src/libjin/Debug/Debug.h @@ -0,0 +1,6 @@ +#ifndef __JIN_DEBUG_H +#define __JIN_DEBUG_H + + + +#endif
\ No newline at end of file diff --git a/src/libjin/Debug/Log.h b/src/libjin/Debug/Log.h new file mode 100644 index 0000000..e1624f5 --- /dev/null +++ b/src/libjin/Debug/Log.h @@ -0,0 +1,14 @@ +#ifndef __JIN_LOG_H +#define __JIN_LOG_H + +namespace jin +{ +namespace debug +{ + + const char* err; + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Input/Event.cpp b/src/libjin/Input/Event.cpp new file mode 100644 index 0000000..8eb45e6 --- /dev/null +++ b/src/libjin/Input/Event.cpp @@ -0,0 +1,7 @@ +#include "event.h" +#include "SDL2\SDL.h" + +namespace jin +{ + +}
\ No newline at end of file diff --git a/src/libjin/Input/Event.h b/src/libjin/Input/Event.h new file mode 100644 index 0000000..e09f422 --- /dev/null +++ b/src/libjin/Input/Event.h @@ -0,0 +1,13 @@ +#ifndef __JIN_EVENT_H +#define __JIN_EVENT_H +namespace jin +{ +namespace input +{ + + + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Input/Input.h b/src/libjin/Input/Input.h new file mode 100644 index 0000000..217edd2 --- /dev/null +++ b/src/libjin/Input/Input.h @@ -0,0 +1,8 @@ +#ifndef __JIN_INPUT_H +#define __JIN_INPUT_H + +#include "event.h" +#include "keyboard.h" +#include "mouse.h" + +#endif
\ No newline at end of file diff --git a/src/libjin/Input/Joypad.cpp b/src/libjin/Input/Joypad.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Input/Joypad.cpp diff --git a/src/libjin/Input/Joypad.h b/src/libjin/Input/Joypad.h new file mode 100644 index 0000000..e8d309b --- /dev/null +++ b/src/libjin/Input/Joypad.h @@ -0,0 +1,14 @@ +#ifndef __JIN_JOYPAD_H +#define __JIN_JOYPAD_H + +namespace jin +{ +namespace input +{ + + + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Input/Keyboard.cpp b/src/libjin/Input/Keyboard.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Input/Keyboard.cpp diff --git a/src/libjin/Input/Keyboard.h b/src/libjin/Input/Keyboard.h new file mode 100644 index 0000000..bbb6456 --- /dev/null +++ b/src/libjin/Input/Keyboard.h @@ -0,0 +1,13 @@ +#ifndef __JIN_KEYBOARD_H +#define __JIN_KEYBOARD_H +namespace jin +{ +namespace input +{ + class Keyboard + { + + }; +} +} +#endif
\ No newline at end of file diff --git a/src/libjin/Input/Mouse.cpp b/src/libjin/Input/Mouse.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Input/Mouse.cpp diff --git a/src/libjin/Input/Mouse.h b/src/libjin/Input/Mouse.h new file mode 100644 index 0000000..b926327 --- /dev/null +++ b/src/libjin/Input/Mouse.h @@ -0,0 +1,15 @@ +#ifndef __JIN_MOUSE_H +#define __JIN_MOUSE_H +namespace jin +{ +namespace input +{ + class Mouse + { + public: + + }; + +} +} +#endif
\ No newline at end of file diff --git a/src/libjin/Math/Math.h b/src/libjin/Math/Math.h new file mode 100644 index 0000000..849f74b --- /dev/null +++ b/src/libjin/Math/Math.h @@ -0,0 +1,16 @@ +#ifndef __JIN_UTILS_MATH_H +#define __JIN_UTILS_MATH_H + +#include <math.h> + +#include "constant.h" +#include "matrix.h" +#include "quad.h" + +#define min(a,b) (a < b ? a : b) +#define max(a,b) (a > b ? a : b) +#define clamp(a, mi,ma) (min(max(a,mi),ma)) +#define within(a,min,max) (a >= min && a <= max) +#define without(a,min,max) (a < min || a > max) + +#endif
\ No newline at end of file diff --git a/src/libjin/Math/Matrix.cpp b/src/libjin/Math/Matrix.cpp new file mode 100644 index 0000000..97e9178 --- /dev/null +++ b/src/libjin/Math/Matrix.cpp @@ -0,0 +1,177 @@ +#include "Matrix.h" + +#include <cstring> // memcpy +#include <cmath> + +namespace jin +{ +namespace math +{ + + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + + Matrix::Matrix() + { + setIdentity(); + } + + Matrix::~Matrix() + { + } + + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + + Matrix Matrix::operator * (const Matrix & m) const + { + Matrix t; + + t.e[0] = (e[0] * m.e[0]) + (e[4] * m.e[1]) + (e[8] * m.e[2]) + (e[12] * m.e[3]); + t.e[4] = (e[0] * m.e[4]) + (e[4] * m.e[5]) + (e[8] * m.e[6]) + (e[12] * m.e[7]); + t.e[8] = (e[0] * m.e[8]) + (e[4] * m.e[9]) + (e[8] * m.e[10]) + (e[12] * m.e[11]); + t.e[12] = (e[0] * m.e[12]) + (e[4] * m.e[13]) + (e[8] * m.e[14]) + (e[12] * m.e[15]); + + t.e[1] = (e[1] * m.e[0]) + (e[5] * m.e[1]) + (e[9] * m.e[2]) + (e[13] * m.e[3]); + t.e[5] = (e[1] * m.e[4]) + (e[5] * m.e[5]) + (e[9] * m.e[6]) + (e[13] * m.e[7]); + t.e[9] = (e[1] * m.e[8]) + (e[5] * m.e[9]) + (e[9] * m.e[10]) + (e[13] * m.e[11]); + t.e[13] = (e[1] * m.e[12]) + (e[5] * m.e[13]) + (e[9] * m.e[14]) + (e[13] * m.e[15]); + + t.e[2] = (e[2] * m.e[0]) + (e[6] * m.e[1]) + (e[10] * m.e[2]) + (e[14] * m.e[3]); + t.e[6] = (e[2] * m.e[4]) + (e[6] * m.e[5]) + (e[10] * m.e[6]) + (e[14] * m.e[7]); + t.e[10] = (e[2] * m.e[8]) + (e[6] * m.e[9]) + (e[10] * m.e[10]) + (e[14] * m.e[11]); + t.e[14] = (e[2] * m.e[12]) + (e[6] * m.e[13]) + (e[10] * m.e[14]) + (e[14] * m.e[15]); + + t.e[3] = (e[3] * m.e[0]) + (e[7] * m.e[1]) + (e[11] * m.e[2]) + (e[15] * m.e[3]); + t.e[7] = (e[3] * m.e[4]) + (e[7] * m.e[5]) + (e[11] * m.e[6]) + (e[15] * m.e[7]); + t.e[11] = (e[3] * m.e[8]) + (e[7] * m.e[9]) + (e[11] * m.e[10]) + (e[15] * m.e[11]); + t.e[15] = (e[3] * m.e[12]) + (e[7] * m.e[13]) + (e[11] * m.e[14]) + (e[15] * m.e[15]); + + return t; + } + + void Matrix::operator *= (const Matrix & m) + { + Matrix t = (*this) * m; + memcpy((void*)this->e, (void*)t.e, sizeof(float) * 16); + } + + const float * Matrix::getElements() const + { + return e; + } + + void Matrix::setIdentity() + { + memset(e, 0, sizeof(float) * 16); + e[0] = e[5] = e[10] = e[15] = 1; + } + + void Matrix::setTranslation(float x, float y) + { + setIdentity(); + e[12] = x; + e[13] = y; + } + + void Matrix::setRotation(float rad) + { + setIdentity(); + float c = cos(rad), s = sin(rad); + e[0] = c; e[4] = -s; + e[1] = s; e[5] = c; + } + + void Matrix::setScale(float sx, float sy) + { + setIdentity(); + e[0] = sx; + e[5] = sy; + } + + void Matrix::setShear(float kx, float ky) + { + setIdentity(); + e[1] = ky; + e[4] = kx; + } + + void Matrix::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy) + { + memset(e, 0, sizeof(float) * 16); // zero out matrix + float c = cos(angle), s = sin(angle); + // matrix multiplication carried out on paper: + // |1 x| |c -s | |sx | |1 -ox| + // | 1 y| |s c | | sy | | 1 -oy| + // | 1 | | 1 | | 1 | | 1 | + // | 1| | 1| | 1| | 1 | + // move rotate scale origin + e[10] = e[15] = 1.0f; + e[0] = c * sx ; // = a + e[1] = s * sx ; // = b + e[4] = - s * sy; // = c + e[5] = c * sy; // = d + e[12] = x - ox * e[0] - oy * e[4]; + e[13] = y - ox * e[1] - oy * e[5]; + } + + void Matrix::translate(float x, float y) + { + Matrix t; + t.setTranslation(x, y); + this->operator *=(t); + } + + void Matrix::rotate(float rad) + { + Matrix t; + t.setRotation(rad); + this->operator *=(t); + } + + void Matrix::scale(float sx, float sy) + { + Matrix t; + t.setScale(sx, sy); + this->operator *=(t); + } + + void Matrix::shear(float kx, float ky) + { + Matrix t; + t.setShear(kx, ky); + this->operator *=(t); + } + + // | x | + // | y | + // | 0 | + // | 1 | + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + + void Matrix::transform(vertex * dst, const vertex * src, int size) const + { + for (int i = 0; i<size; ++i) + { + // Store in temp variables in case src = dst + float x = (e[0] * src[i].x) + (e[4] * src[i].y) + (0) + (e[12]); + float y = (e[1] * src[i].x) + (e[5] * src[i].y) + (0) + (e[13]); + + dst[i].x = x; + dst[i].y = y; + } + } + +} +}
\ No newline at end of file diff --git a/src/libjin/Math/Matrix.h b/src/libjin/Math/Matrix.h new file mode 100644 index 0000000..673d253 --- /dev/null +++ b/src/libjin/Math/Matrix.h @@ -0,0 +1,153 @@ +#ifndef __JIN_MATRIX_H +#define __JIN_MATRIX_H +#include <math.h> +namespace jin +{ +namespace math +{ + + struct vertex + { + unsigned char r, g, b, a; + float x, y; + float s, t; + }; + /** + * This class is the basis for all transformations in LOVE. Althought not + * really needed for 2D, it contains 4x4 elements to be compatible with + * OpenGL without conversions. + **/ + class Matrix + { + private: + + /** + * | e0 e4 e8 e12 | + * | e1 e5 e9 e13 | + * | e2 e6 e10 e14 | + * | e3 e7 e11 e15 | + **/ + float e[16]; + + public: + + /** + * Creates a new identity matrix. + **/ + Matrix(); + + /** + * Destructor. + **/ + ~Matrix(); + + /** + * Multiplies this Matrix with another Matrix, changing neither. + * @param m The Matrix to multiply with this Matrix. + * @return The combined matrix. + **/ + Matrix operator * (const Matrix & m) const; + + /** + * Multiplies a Matrix into this Matrix. + * @param m The Matrix to combine into this Matrix. + **/ + void operator *= (const Matrix & m); + + /** + * Gets a pointer to the 16 array elements. + * @return The array elements. + **/ + const float * getElements() const; + + /** + * Resets this Matrix to the identity matrix. + **/ + void setIdentity(); + + /** + * Resets this Matrix to a translation. + * @param x Translation along x-axis. + * @param y Translation along y-axis. + **/ + void setTranslation(float x, float y); + + /** + * Resets this Matrix to a rotation. + * @param r The angle in radians. + **/ + void setRotation(float r); + + /** + * Resets this Matrix to a scale transformation. + * @param sx Scale factor along the x-axis. + * @param sy Scale factor along the y-axis. + **/ + void setScale(float sx, float sy); + + /** + * Resets this Matrix to a shear transformation. + * @param kx Shear along x-axis. + * @param ky Shear along y-axis. + **/ + void setShear(float kx, float ky); + + /** + * Creates a transformation with a certain position, orientation, scale + * and offset. Perfect for Drawables -- what a coincidence! + * + * @param x The translation along the x-axis. + * @param y The translation along the y-axis. + * @param angle The rotation (rad) around the center with offset (ox,oy). + * @param sx Scale along x-axis. + * @param sy Scale along y-axis. + * @param ox The offset for rotation along the x-axis. + * @param oy The offset for rotation along the y-axis. + * @param kx Shear along x-axis + * @param ky Shear along y-axis + **/ + void setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy); + + /** + * Multiplies this Matrix with a translation. + * @param x Translation along x-axis. + * @param y Translation along y-axis. + **/ + void translate(float x, float y); + + /** + * Multiplies this Matrix with a rotation. + * @param r Angle in radians. + **/ + void rotate(float r); + + /** + * Multiplies this Matrix with a scale transformation. + * @param sx Scale factor along the x-axis. + * @param sy Scale factor along the y-axis. + **/ + void scale(float sx, float sy); + + /** + * Multiplies this Matrix with a shear transformation. + * @param kx Shear along the x-axis. + * @param ky Shear along the y-axis. + **/ + void shear(float kx, float ky); + + /** + * Transforms an array of vertices by this Matrix. The sources and + * destination arrays may be the same. + * + * @param dst Storage for the transformed vertices. + * @param src The source vertices. + * @param size The number of vertices. + **/ + void transform(vertex * dst, const vertex * src, int size) const; + + }; + +} +} + +#endif diff --git a/src/libjin/Math/Quad.h b/src/libjin/Math/Quad.h new file mode 100644 index 0000000..a50cc9e --- /dev/null +++ b/src/libjin/Math/Quad.h @@ -0,0 +1,17 @@ +#ifndef __JIN_QUAD_H +#define __JIN_QUAD_H + +namespace jin +{ +namespace math +{ + + struct Quad + { + float x, y, w, h; + }; + +} +} + +#endif diff --git a/src/libjin/Math/Vector.cpp b/src/libjin/Math/Vector.cpp new file mode 100644 index 0000000..f26d0c4 --- /dev/null +++ b/src/libjin/Math/Vector.cpp @@ -0,0 +1,2 @@ +#include "vector.h" + diff --git a/src/libjin/Math/Vector.h b/src/libjin/Math/Vector.h new file mode 100644 index 0000000..43e249e --- /dev/null +++ b/src/libjin/Math/Vector.h @@ -0,0 +1,14 @@ +#ifndef __JIN_VECTOR_H +#define __JIN_VECTOR_H + +namespace jin +{ +namespace math +{ + + + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Math/constant.h b/src/libjin/Math/constant.h new file mode 100644 index 0000000..f2f740f --- /dev/null +++ b/src/libjin/Math/constant.h @@ -0,0 +1,10 @@ +#ifndef __JIN_MATH_CONSTANT_H +#define __JIN_MATH_CONSTANT_H + +#define PI 3.1415926f + +// int16 Χ +#define INT16_RANGE_LEFT -32768 +#define INT16_RANGE_RIGHT 32767 + +#endif
\ No newline at end of file diff --git a/src/libjin/Net/Net.cpp b/src/libjin/Net/Net.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Net/Net.cpp diff --git a/src/libjin/Net/Net.h b/src/libjin/Net/Net.h new file mode 100644 index 0000000..6b86a45 --- /dev/null +++ b/src/libjin/Net/Net.h @@ -0,0 +1,6 @@ +#ifndef __JIN_NET_H +#define __JIN_NET_H + + + +#endif
\ No newline at end of file diff --git a/src/libjin/Physics/Physics.h b/src/libjin/Physics/Physics.h new file mode 100644 index 0000000..9927301 --- /dev/null +++ b/src/libjin/Physics/Physics.h @@ -0,0 +1,12 @@ +#ifndef __JIN_PHYSICS_H +#define __JIN_PHYSICS_H + +namespace jin +{ +namespace physics +{ + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Physics/Rigid.h b/src/libjin/Physics/Rigid.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Physics/Rigid.h diff --git a/src/libjin/Render/Canvas.cpp b/src/libjin/Render/Canvas.cpp new file mode 100644 index 0000000..8cb34ca --- /dev/null +++ b/src/libjin/Render/Canvas.cpp @@ -0,0 +1,134 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "../utils/macros.h" +#include "canvas.h" +#include "window.h" + +namespace jin +{ +namespace render +{ + + shared Canvas* Canvas::createCanvas(int w, int h) + { + return new Canvas(w, h); + } + + Canvas::Canvas(int w, int h) + : Drawable(w, h) + { + init(); + } + + Canvas::~Canvas() + { + } + + shared GLint Canvas::cur = -1; + + bool Canvas::init() + { + setVertices( + new float [DRAWABLE_V_SIZE] { + 0, 0, + 0, (float)height, + (float)width, (float)height, + (float)width, 0, + }, + new float [DRAWABLE_V_SIZE] { + 0, 1, + 0, 0, + 1, 0, + 1, 1 + } + ); + + GLint current_fbo; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo); + + // generate a new render buffer object + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // generate texture save target + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + // unbind framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) + return false; + return true; + } + + bool Canvas::hasbind(GLint fbo) + { + return cur == fbo; + } + + /** + * bind to canvas + */ + void Canvas::bind() + { + if (hasbind(fbo)) return; + + cur = fbo; + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glViewport(0, 0, width, height); + glOrtho(0, width, height, 0, -1, 1); + + // Switch back to modelview matrix + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + } + + /** + * bind to default screen render buffer. + */ + shared void Canvas::unbind() + { + if (hasbind(0)) return; + + cur = 0; + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + WindowSystem* wnd = WindowSystem::get(); + int ww = wnd->getW(), + wh = wnd->getH(); + + glViewport(0, 0, ww, wh); + + // load back to normal + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + // set viewport matrix + glOrtho(0, ww, wh, 0, -1, 1); + + // switch to model matrix + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + } + +} +} +#endif // JIN_MODULES_RENDER
\ No newline at end of file diff --git a/src/libjin/Render/Canvas.h b/src/libjin/Render/Canvas.h new file mode 100644 index 0000000..8cced23 --- /dev/null +++ b/src/libjin/Render/Canvas.h @@ -0,0 +1,40 @@ +#ifndef __JIN_CANVAS_H +#define __JIN_CANVAS_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "drawable.h" +namespace jin +{ +namespace render +{ + class Canvas: public Drawable + { + public: + + static Canvas* createCanvas(int w, int h); + + ~Canvas(); + + void bind(); + + static void unbind(); + + static bool hasbind(GLint fbo); + + private: + + Canvas(int w, int h); + + GLuint fbo; + + // current binded fbo + static GLint cur; + + bool init(); + }; +} +} + +#endif +#endif // JIN_MODULES_RENDER diff --git a/src/libjin/Render/Color.h b/src/libjin/Render/Color.h new file mode 100644 index 0000000..7b88799 --- /dev/null +++ b/src/libjin/Render/Color.h @@ -0,0 +1,31 @@ +/** +* Some color operating here. +*/ +#ifndef __JIN_COLOR_H +#define __JIN_COLOR_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "../utils/endian.h" + +namespace jin +{ +namespace render +{ + + union color { + struct { +#if JIN_BYTEORDER == JIN_BIG_ENDIAN + unsigned char r, g, b, a; +#else + unsigned char a, b, g, r; +#endif + }rgba; + int word; + }; + +} +} + +#endif // JIN_MODULES_RENDER +#endif
\ No newline at end of file diff --git a/src/libjin/Render/Drawable.cpp b/src/libjin/Render/Drawable.cpp new file mode 100644 index 0000000..cbdf250 --- /dev/null +++ b/src/libjin/Render/Drawable.cpp @@ -0,0 +1,77 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "drawable.h" +#include "../math/matrix.h" +#include <stdlib.h> + +namespace jin +{ +namespace render +{ + Drawable::Drawable(int w, int h):texture(0), width(w), height(h), ancx(0), ancy(0), textCoord(0), vertCoord(0) + { + } + + Drawable::~Drawable() + { + glDeleteTextures(1, &texture); + delete[] vertCoord; + delete[] textCoord; + } + + void Drawable::setVertices(float* v, float* t) + { + // render area + if (vertCoord) + delete[] vertCoord; + vertCoord = v; + + // textrue + if (textCoord) + delete[] textCoord; + textCoord = t; + } + + void Drawable::setAnchor(int x, int y) + { + ancx = x; + ancy = y; + } + + void Drawable::draw(int x, int y, float sx, float sy, float r) + { + // Must set textCoord and vertCoord before renderring + if (! textCoord||! vertCoord) return; + + static jin::math::Matrix t; + t.setTransformation(x, y, r, sx, sy, ancx, ancy); + + glEnable(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, texture); + + // push modle matrix + glPushMatrix(); + glMultMatrixf((const GLfloat*)t.getElements()); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, textCoord); + glVertexPointer(2, GL_FLOAT, 0, vertCoord); + glDrawArrays(GL_QUADS, 0, 4); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + // pop the model matrix + glPopMatrix(); + + // bind texture to default screen + glBindTexture(GL_TEXTURE_2D, 0); + + glDisable(GL_TEXTURE_2D); + } +} +} + +#endif // JIN_MODULES_RENDER
\ No newline at end of file diff --git a/src/libjin/Render/Drawable.h b/src/libjin/Render/Drawable.h new file mode 100644 index 0000000..f8e25a2 --- /dev/null +++ b/src/libjin/Render/Drawable.h @@ -0,0 +1,56 @@ +#ifndef __JIN_DRAWABLE +#define __JIN_DRAWABLE +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "3rdparty/GLee/GLee.h" +namespace jin +{ +namespace render +{ + class Drawable + { + public: + Drawable(int w = 0, int h = 0); + virtual ~Drawable(); + + void setAnchor(int x, int y); + + void draw(int x, int y, float sx, float sy, float r); + + inline int Drawable::getWidth() const + { + return width; + } + + inline int Drawable::getHeight() const + { + return height; + } + + inline GLuint getTexture() const + { + return texture; + }; + + protected: +#define DRAWABLE_V_SIZE 8 + void setVertices(float* v, float* t); + + GLuint texture; + + int width, height; + + /* anchor point */ + int ancx, ancy; + + // render coords + float* textCoord; + float* vertCoord; + + }; +} +}// jin + +#endif // JIN_MODULES_RENDER +#endif diff --git a/src/libjin/Render/Font.cpp b/src/libjin/Render/Font.cpp new file mode 100644 index 0000000..e8e71b2 --- /dev/null +++ b/src/libjin/Render/Font.cpp @@ -0,0 +1,193 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "font.h" +#include <stdio.h> +#define STB_TRUETYPE_IMPLEMENTATION +#include "3rdparty/stb/stb_truetype.h" +#include "color.h" + +namespace jin +{ +namespace render +{ + + using namespace jin::math; + +#define BITMAP_WIDTH 512 +#define BITMAP_HEIGHT 512 +#define PIXEL_HEIGHT 32 + + Font::Font():Drawable() + { + } + + // ttf file read buffer + static unsigned char ttf_buffer[1 << 20]; + + // bitmap for saving font data + static unsigned char temp_bitmap[BITMAP_WIDTH * BITMAP_HEIGHT]; + + void Font::loadf(const char* path) + { + fread(ttf_buffer, 1, 1 << 20, fopen(path, "rb")); + + loadb(ttf_buffer); + } + + /** + * load from memory + */ + void Font::loadb(const unsigned char* data) + { + stbtt_BakeFontBitmap(data, 0, PIXEL_HEIGHT, temp_bitmap, BITMAP_WIDTH, BITMAP_HEIGHT, 32, 96, cdata); + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_WIDTH, + BITMAP_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, 0); + } + + /** + * get texture quad + */ + static Quad getCharQuad(const stbtt_bakedchar* chardata, int pw, int ph, int char_index) + { + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + Quad q; + q.x = b->x0 * ipw; + q.y = b->y0 * iph; + q.w = b->x1 * ipw - b->x0 * ipw; + q.h = b->y1 * iph - b->y0 * iph; + return q; + } + + /** + * render function draw mutiple times + * in loop + */ + void Font::render( + const char* text, // rendered text + float x, float y, // render position + int fheight, // font height + int spacing, // font spacing + int lheight) // line height + { + float _x = x, + _y = y; + + int len = strlen(text); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texture); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // for saving clip quad + stbtt_aligned_quad q; + + // render every given character + int xc = x; + int yc = y; + + float factor = fheight / (float)PIXEL_HEIGHT; + + for (int i = 0; i < len; ++i) + { + char c = text[i]; + if (c == '\n') + { + xc = x; + yc += lheight; + continue; + } + + // only support ASCII + Quad q = getCharQuad(cdata, 512, 512, c - 32); + float s0 = q.x, + s1 = q.x + q.w, + t0 = q.y, + t1 = q.y + q.h; + + // texture quad + float tc[] = { + s0, t1, + s1, t1, + s1, t0, + s0, t0 + }; + + // character bound box + stbtt_bakedchar box = cdata[c - 32]; + + float width = factor * (box.x1 - box.x0); + float height = factor * (box.y1 - box.y0); + float xoffset = factor * box.xoff; + // I don't know why add PIXEL_HEIGHT to box.yoff, but + // it works. + float yoffset = factor * (box.yoff + PIXEL_HEIGHT); + float xadvance = factor * box.xadvance; + + // render quad + float vc[] = { + xc + xoffset, yc + height + yoffset, + xc + width + xoffset, yc + height + yoffset, + xc + width + xoffset, yc + yoffset, + xc + xoffset, yc + yoffset + }; + + // forward to next character + xc += xadvance + spacing; + + glTexCoordPointer(2, GL_FLOAT, 0, tc); + glVertexPointer(2, GL_FLOAT, 0, vc); + glDrawArrays(GL_QUADS, 0, 4); + } + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + } + + void Font::box(const char* str, int fheight, int spacing, int lheight, int* w, int * h) + { + int len = strlen(str); + + float xc = 0; + int yc = len ? lheight: 0; + int maxX = 0; + + float factor = fheight / (float)PIXEL_HEIGHT; + + for (int i = 0; i < len; ++i) + { + char c = str[i]; + if (c == '\n') + { + yc += lheight; + xc = 0; + continue; + } + stbtt_bakedchar box = cdata[c - 32]; + + xc += factor * box.xadvance + spacing; + if (xc > maxX) maxX = xc; + } + + *w = maxX; + *h = yc; + } + +} +} +#endif // JIN_MODULES_RENDER
\ No newline at end of file diff --git a/src/libjin/Render/Font.h b/src/libjin/Render/Font.h new file mode 100644 index 0000000..f2a57ed --- /dev/null +++ b/src/libjin/Render/Font.h @@ -0,0 +1,61 @@ +#ifndef __JIN_FONT_H +#define __JIN_FONT_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "drawable.h" +#include "3rdparty/stb/stb_truetype.h" +#include "../math/quad.h" + +namespace jin +{ +namespace render +{ + /** + * Usage of stb_truetype.h here might be a little + * bit dummy. Implementation of Font is referring + * to stb_truetype.h L243~284. I basicly copy it:) + */ + class Font: public Drawable + { + public: + + Font(); + + /** + * load ttf font data from .ttf + */ + void loadf(const char* file); + + /** + * load ttf font data from memory + */ + void loadb(const unsigned char* data); + + /** + * render text to screen + */ + void render( + const char* str, // rendered text + float x, float y, // render position + int fheight, // font size + int spacing, // font spacing + int lheight // line height + ); + + void box(const char* str, int fheight, int spacing, int lheight, int* w, int * h); + + private: + + /** + * ASCII 32(space)..126(~) is 95 glyphs + */ + stbtt_bakedchar cdata[96]; + + }; + +} +} + +#endif // JIN_MODULES_RENDER +#endif
\ No newline at end of file diff --git a/src/libjin/Render/Graphics.cpp b/src/libjin/Render/Graphics.cpp new file mode 100644 index 0000000..f54021b --- /dev/null +++ b/src/libjin/Render/Graphics.cpp @@ -0,0 +1,121 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "graphics.h" +#include "../math/matrix.h" +#include "../math/constant.h" +#include <string> +namespace jin +{ +namespace render +{ + + void point(int x, int y) + { + float vers[] = { x + 0.5f , y + 0.5f }; + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)vers); + glDrawArrays(GL_POINTS, 0, 1); + glDisableClientState(GL_VERTEX_ARRAY); + } + + void points(int n, GLshort* p) + { + glEnableClientState(GL_VERTEX_ARRAY); + + glVertexPointer(2, GL_SHORT, 0, (GLvoid*)p); + glDrawArrays(GL_POINTS, 0, n); + + glDisableClientState(GL_VERTEX_ARRAY); + } + + void line(int x1, int y1, int x2, int y2) + { + glDisable(GL_TEXTURE_2D); + float verts[] = { + x1, y1, + x2, y2 + }; + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)verts); + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + } + + void circle(RENDER_MODE mode, int x, int y, int r) + { + r = r < 0 ? 0 : r; + + int points = 40; + float two_pi = static_cast<float>(PI * 2); + if (points <= 0) points = 1; + float angle_shift = (two_pi / points); + float phi = .0f; + + float *coords = new float[2 * (points + 1)]; + for (int i = 0; i < points; ++i, phi += angle_shift) + { + coords[2 * i] = x + r * cos(phi); + coords[2 * i + 1] = y + r * sin(phi); + } + + coords[2 * points] = coords[0]; + coords[2 * points + 1] = coords[1]; + + polygon(mode, coords, points); + + delete[] coords; + } + + void rect(RENDER_MODE mode, int x, int y, int w, int h) + { + float coords[] = { x, y, x + w, y, x + w, y + h, x, y + h }; + polygon(mode, coords, 4); + } + + void triangle(RENDER_MODE mode, int x1, int y1, int x2, int y2, int x3, int y3) + { + float coords[] = { x1, y1, x2, y2, x3, y3 }; + polygon(mode, coords, 3); + } + + void polygon_line(float* p, int count) + { + float* verts = new float[count * 4]; + for (int i = 0; i < count; ++i) + { + // each line has two point n,n+1 + verts[i * 4] = p[i * 2]; + verts[i * 4 + 1] = p[i * 2 + 1]; + verts[i * 4 + 2] = p[(i + 1) % count * 2]; + verts[i * 4 + 3] = p[(i + 1) % count * 2 + 1]; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)verts); + glDrawArrays(GL_LINES, 0, count * 2); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] verts; + } + + void polygon(RENDER_MODE mode, float* p, int count) + { + if (mode == LINE) + { + polygon_line(p, count); + } + else if (mode == FILL) + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)p); + glDrawArrays(GL_POLYGON, 0, count); + glDisableClientState(GL_VERTEX_ARRAY); + } + } + +} +} + +#endif // JIN_MODULES_RENDER
\ No newline at end of file diff --git a/src/libjin/Render/Graphics.h b/src/libjin/Render/Graphics.h new file mode 100644 index 0000000..13dd4d1 --- /dev/null +++ b/src/libjin/Render/Graphics.h @@ -0,0 +1,40 @@ +#ifndef __JIN_GRAPHICS_H +#define __JIN_GRAPHICS_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "color.h" +#include "canvas.h" +#include "texture.h" + +namespace jin +{ +namespace render +{ + typedef enum { + NONE = 0, + FILL , + LINE + }RENDER_MODE; + + /** + * TODO: + * drawPixels(int n, points) + */ + extern void line(int x1, int y1, int x2, int y2); + + extern void rect(RENDER_MODE mode, int x, int y, int w, int h); + + extern void triangle(RENDER_MODE mode, int x1, int y1, int x2, int y2, int x3, int y3); + + extern void circle(RENDER_MODE mode, int x, int y, int r); + + extern void point(int x, int y); + + extern void points(int n, GLshort* p, GLubyte* c); + + extern void polygon(RENDER_MODE mode, float* p, int count); +} +} +#endif // JIN_MODULES_RENDER +#endif // __JIN_GRAPHICS_H diff --git a/src/libjin/Render/JSL.cpp b/src/libjin/Render/JSL.cpp new file mode 100644 index 0000000..4ce660b --- /dev/null +++ b/src/libjin/Render/JSL.cpp @@ -0,0 +1,158 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "../utils/macros.h" +#include "jsl.h" +namespace jin +{ +namespace render +{ + //vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) + static const char* base_f = " " + //"#version 120 \n" + "#define number float \n" + "#define Image sampler2D \n" + "#define Canvas sampler2D \n" + "#define Color vec4 \n" + "#define Texel texture2D \n" + "#define extern uniform \n" + "uniform Image _tex0_; \n" + "%s \n" + "void main(){ \n" + " gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);\n" + "}\0"; + + shared JSLProgram* JSLProgram::currentJSLProgram = nullptr; + + JSLProgram* JSLProgram::createJSLProgram(const char* program) + { + return new JSLProgram(program); + } + + JSLProgram::JSLProgram(const char* program) + : currentTextureUnit(0) + { + initialize(program); + } + + JSLProgram::~JSLProgram() + { + destroy(); + } + + inline void JSLProgram::destroy() + { + if (currentJSLProgram == this) + unuse(); + } + + inline void JSLProgram::initialize(const char* program) + { + char* fs = (char*)alloca(strlen(program) + strlen(base_f)); + sprintf(fs, base_f, program); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, (const GLchar**)&fs, NULL); + glCompileShader(fragmentShader); + + pid = glCreateProgram(); + glAttachShader(pid, fragmentShader); + glLinkProgram(pid); + } + + static inline GLint getMaxTextureUnits() + { + GLint maxTextureUnits = 0; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); + return maxTextureUnits; + } + + GLint JSLProgram::getTextureUnit(const std::string& name) + { + std::map<std::string, GLint>::iterator texture_unit = texturePool.find(name); + if (texture_unit != texturePool.end()) + return texture_unit->second; + static GLint maxTextureUnits = getMaxTextureUnits(); + if (++currentTextureUnit >= maxTextureUnits) + return 0; + texturePool[name] = currentTextureUnit; + return currentTextureUnit; + } + +#define checkJSL() if (currentJSLProgram != this) return + + void JSLProgram::sendFloat(const char* variable, float number) + { + checkJSL(); + + int loc = glGetUniformLocation(pid, variable); + glUniform1f(loc, number); + } + + void JSLProgram::sendTexture(const char* variable, const Texture* tex) + { + checkJSL(); + + GLint location = glGetUniformLocation(pid, variable); + if (location == -1) + return; + GLint texture_unit = getTextureUnit(variable); + glUniform1i(location, texture_unit); + glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, tex->getTexture()); + glActiveTexture(GL_TEXTURE0); + } + + void JSLProgram::sendCanvas(const char* variable, const Canvas* canvas) + { + checkJSL(); + + GLint location = glGetUniformLocation(pid, variable); + if (location == -1) + return; + GLint texture_unit = getTextureUnit(variable); + glUniform1i(location, texture_unit); + glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, canvas->getTexture()); + glActiveTexture(GL_TEXTURE0); + } + + void JSLProgram::sendVec2(const char* name, float x, float y) + { + checkJSL(); + + int loc = glGetUniformLocation(pid, name); + glUniform2f(loc, x, y); + } + + void JSLProgram::sendVec3(const char* name, float x, float y, float z) + { + checkJSL(); + + int loc = glGetUniformLocation(pid, name); + glUniform3f(loc, x, y, z); + } + + void JSLProgram::sendVec4(const char* name, float x, float y, float z, float w) + { + checkJSL(); + + int loc = glGetUniformLocation(pid, name); + glUniform4f(loc, x, y, z, w); + } + + void JSLProgram::sendColor(const char* name, const color* col) + { + checkJSL(); + + int loc = glGetUniformLocation(pid, name); + glUniform4f(loc, + col->rgba.r / 255.f, + col->rgba.g / 255.f, + col->rgba.b / 255.f, + col->rgba.a / 255.f + ); + } + +} +} +#endif // JIN_MODULES_RENDER diff --git a/src/libjin/Render/JSL.h b/src/libjin/Render/JSL.h new file mode 100644 index 0000000..741983a --- /dev/null +++ b/src/libjin/Render/JSL.h @@ -0,0 +1,74 @@ +#ifndef __JIN_JSL_H +#define __JIN_JSL_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include <string> +#include <map> +#include "color.h" +#include "texture.h" +#include "canvas.h" +#include "3rdparty/GLee/GLee.h" + +namespace jin +{ +namespace render +{ + + class JSLProgram + { + + public: + + static JSLProgram* createJSLProgram(const char* program); + + ~JSLProgram(); + + inline void JSLProgram::use() + { + glUseProgram(pid); + currentJSLProgram = this; + } + + static inline void JSLProgram::unuse() + { + glUseProgram(0); + currentJSLProgram = nullptr; + } + + void sendFloat(const char* name, float number); + void sendTexture(const char* name, const Texture* image); + void sendVec2(const char* name, float x, float y); + void sendVec3(const char* name, float x, float y, float z); + void sendVec4(const char* name, float x, float y, float z, float w); + void sendCanvas(const char* name, const Canvas* canvas); + void sendColor(const char* name, const color* col); + + static inline JSLProgram* getCurrentJSL() + { + return currentJSLProgram; + } + + private: + + JSLProgram(const char* program); + + static JSLProgram* currentJSLProgram; + + GLuint pid; + + std::map<std::string, GLint> texturePool; + + GLint currentTextureUnit; + GLint getTextureUnit(const std::string& name); + + inline void initialize(const char* program); + inline void destroy(); + + }; + +} +} + +#endif // JIN_MODULES_RENDER +#endif diff --git a/src/libjin/Render/Render.h b/src/libjin/Render/Render.h new file mode 100644 index 0000000..e51051e --- /dev/null +++ b/src/libjin/Render/Render.h @@ -0,0 +1,15 @@ +#ifndef __JIN_RENDER_H +#define __JIN_RENDER_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "canvas.h" +#include "color.h" +#include "font.h" +#include "graphics.h" +#include "texture.h" +#include "jsl.h" +#include "window.h" + +#endif // JIN_MODULES_RENDER +#endif
\ No newline at end of file diff --git a/src/libjin/Render/Texture.cpp b/src/libjin/Render/Texture.cpp new file mode 100644 index 0000000..cee3552 --- /dev/null +++ b/src/libjin/Render/Texture.cpp @@ -0,0 +1,99 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include <fstream> +#include "texture.h" +#include "3rdparty/stb/stb_image.h" +#include "../utils/utils.h" +#include "../math/math.h" + +namespace jin +{ +namespace render +{ + + Texture* Texture::createTexture(const char* file) + { + std::ifstream fs; + fs.open(file, std::ios::binary); + Texture* tex = nullptr; + if (fs.is_open()) + { + fs.seekg(0, std::ios::end); + int size = fs.tellg(); + fs.seekg(0, std::ios::beg); + char* buffer = (char*)malloc(size); + memset(buffer, 0, size); + fs.read(buffer, size); + tex = createTexture(buffer, size); + free(buffer); + } + fs.close(); + return tex; + } + + Texture* Texture::createTexture(const void* mem, size_t size) + { + Texture* tex = new Texture(); + if(!tex->loadb(mem, size)) + { + delete tex; + tex = nullptr; + } + return tex; + } + + Texture::Texture() + : Drawable(), pixels(0) + { + } + + Texture::~Texture() + { + stbi_image_free(pixels); + } + + color Texture::getPixel(int x, int y) + { + if (without(x, 0, width) || without(y, 0, height)) + { + return { 0 }; + } + return pixels[x + y * width]; + } + + bool Texture::loadb(const void* b, size_t size) + { + // ʹstbi_load_from_memory + unsigned char* textureData = stbi_load_from_memory((unsigned char *)b, size, &width, &height, NULL, STBI_rgb_alpha); + if (textureData == 0) return false; + pixels = (color*)textureData; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, + height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData); + + // set render vertices + Drawable::setVertices( + new float [DRAWABLE_V_SIZE] { + 0, 0, + 0, (float)height, + (float)width, (float)height, + (float)width, 0, + }, + new float [DRAWABLE_V_SIZE] { + 0, 0, + 0, 1, + 1, 1, + 1, 0 + } + ); + + return true; + } +} +} +#endif // JIN_MODULES_RENDER
\ No newline at end of file diff --git a/src/libjin/Render/Texture.h b/src/libjin/Render/Texture.h new file mode 100644 index 0000000..d2e4bd0 --- /dev/null +++ b/src/libjin/Render/Texture.h @@ -0,0 +1,38 @@ +#ifndef __JIN_IMAGE_H +#define __JIN_IMAGE_H +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include "3rdparty/GLee/GLee.h" +#include "color.h" +#include "drawable.h" +namespace jin +{ +namespace render +{ + class Texture: public Drawable + { + + public: + + static Texture* createTexture(const char* file); + static Texture* createTexture(const void* mem, size_t size); + + ~Texture(); + + color getPixel(int x, int y); + + private: + + Texture(); + + bool loadb(const void* buffer, size_t size); + + color* pixels; + + }; +} +} + +#endif // JIN_MODULES_RENDER +#endif
\ No newline at end of file diff --git a/src/libjin/Render/Window.cpp b/src/libjin/Render/Window.cpp new file mode 100644 index 0000000..6507691 --- /dev/null +++ b/src/libjin/Render/Window.cpp @@ -0,0 +1,90 @@ +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include <iostream> +#include "window.h" +#include "3rdparty/GLee/GLee.h" +#include "canvas.h" +#include "../utils/utils.h" +#include "../audio/sdl/audio.h" +#include "../utils/log.h" + +namespace jin +{ +namespace render +{ + + onlyonce bool WindowSystem::initSystem(const SettingBase* s) + { + Loghelper::log(Loglevel::LV_INFO, "Init window system"); + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + return false; + + const WindowSetting* setting = (WindowSetting*)s; + + width = setting->width; + height = setting->height; + bool vsync = setting->vsync; + const char* title = setting->title; + + if (wnd) + { + SDL_DestroyWindow(wnd); + SDL_FlushEvent(SDL_WINDOWEVENT); + } + + SDL_GLContext ctx = NULL; + + if (ctx) + { + SDL_GL_DeleteContext(ctx); + } + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + int wx = SDL_WINDOWPOS_UNDEFINED, + wy = SDL_WINDOWPOS_UNDEFINED; + + wnd = SDL_CreateWindow(title, wx, wy, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); + if (wnd == NULL) + return false; + ctx = SDL_GL_CreateContext(wnd); + if (ctx == NULL) + return false; + SDL_GL_SetSwapInterval(vsync ? 1 : 0); + SDL_GL_MakeCurrent(wnd, ctx); + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glColor4f(1, 1, 1, 1); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + Canvas::unbind(); + swapBuffers(); + return true; + } + + onlyonce void WindowSystem::quitSystem() + { + SDL_DestroyWindow(wnd); + } + + inline void WindowSystem::swapBuffers() + { + if (wnd) + SDL_GL_SwapWindow(wnd); + } + +} +} + +#endif // JIN_MODULES_RENDER
\ No newline at end of file diff --git a/src/libjin/Render/Window.h b/src/libjin/Render/Window.h new file mode 100644 index 0000000..77b1963 --- /dev/null +++ b/src/libjin/Render/Window.h @@ -0,0 +1,59 @@ +#ifndef __JIN_RENDER_WINDOW +#define __JIN_RENDER_WINDOW +#include "../modules.h" +#if JIN_MODULES_RENDER + +#include <SDL2/SDL.h> +#include "../utils/utils.h" +#include "../common/subsystem.h" + +namespace jin +{ +namespace render +{ + + class WindowSystem : public Subsystem<WindowSystem> + { + public: + + struct Setting : SettingBase + { + public: + int width, height; // ڴС + bool vsync; // ֱͬ + const char* title; // + }; + + inline int getW() + { + return width; + } + + inline int getH() + { + return height; + } + + inline void swapBuffers(); + + private: + + WindowSystem() {}; + virtual ~WindowSystem() {}; + + SINGLETON(WindowSystem); + + SDL_Window* wnd; + + int width, height; + + onlyonce bool initSystem(const SettingBase* setting) override; + onlyonce void quitSystem() override; + }; + + typedef WindowSystem::Setting WindowSetting; + +} +} +#endif // JIN_MODULES_RENDER +#endif
\ No newline at end of file diff --git a/src/libjin/Thread/Thread.cpp b/src/libjin/Thread/Thread.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Thread/Thread.cpp diff --git a/src/libjin/Thread/Thread.h b/src/libjin/Thread/Thread.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/libjin/Thread/Thread.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/libjin/Tilemap/Tilemap.h b/src/libjin/Tilemap/Tilemap.h new file mode 100644 index 0000000..27cbe51 --- /dev/null +++ b/src/libjin/Tilemap/Tilemap.h @@ -0,0 +1,14 @@ +#ifndef __JIN_TILEMAP_H +#define __JIN_TILEMAP_H + +namespace jin +{ +namespace tilemap +{ + + + +}// tilemap +}// jin + +#endif
\ No newline at end of file diff --git a/src/libjin/Tools/EventMsgCenter/EventMsgCenter.h b/src/libjin/Tools/EventMsgCenter/EventMsgCenter.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/libjin/Tools/EventMsgCenter/EventMsgCenter.h diff --git a/src/libjin/UI/UI.h b/src/libjin/UI/UI.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/libjin/UI/UI.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/libjin/Utils/Log.cpp b/src/libjin/Utils/Log.cpp new file mode 100644 index 0000000..5299942 --- /dev/null +++ b/src/libjin/Utils/Log.cpp @@ -0,0 +1,2 @@ +#define LOGHELPER_IMPLEMENT +#include "log.h"
\ No newline at end of file diff --git a/src/libjin/Utils/Log.h b/src/libjin/Utils/Log.h new file mode 100644 index 0000000..b047402 --- /dev/null +++ b/src/libjin/Utils/Log.h @@ -0,0 +1,134 @@ +/** +* Single.h/loghelper.h +* Copyright (C) 2017~2018 chai +*/ +#ifndef __LOG_HELPER_H +#define __LOG_HELPER_H +#include <string> +#include <iostream> +#include <fstream> +#include <stdarg.h> + +class Loghelper +{ +public: + // logĿ + enum Direction + { + DIR_CERR = 1 << 1, // + DIR_FILE = 1 << 2, // logļ + }; + + // ȼ + enum Level + { + LV_NONE = 0, // none + LV_ERROR = 1 << 1, // error + LV_WARN = 1 << 2, // warn + LV_INFO = 1 << 3, // info + LV_DEBUG = 1 << 4, // debug + LV_ALL = 0xffffffff + }; + + static void log(Level _level, const char* _fmt, ...); + + // ض + static void redirect(unsigned int _dir, char* _path = nullptr); + + // ɸѡȼ + static void restrict(unsigned int levels); + + static void close(); + +private: + static unsigned int dir; // Ŀ + static unsigned int levels; // ȼ + static std::ofstream fs; // ļ +}; + +typedef Loghelper::Level Loglevel; + +#ifdef LOGHELPER_IMPLEMENT + +#define hasbit(flag, bit) ((flag & bit) == bit) + +unsigned int Loghelper::dir = Loghelper::Direction::DIR_CERR; +unsigned int Loghelper::levels = Loghelper::Level::LV_ALL; +std::ofstream Loghelper::fs; + +void Loghelper::log(Level _level, const char* _fmt, ...) +{ + if (!hasbit(levels, _level)) + return; +#define FORMAT_MSG_BUFFER_SIZE (204800) + char* levelStr = nullptr; + switch (_level) + { + case LV_ERROR: + levelStr = "Error: "; + break; + case LV_WARN: + levelStr = "Warn: "; + break; + case LV_INFO: + levelStr = "Info: "; + break; + case LV_DEBUG: + levelStr = "Debug: "; + break; + default: + levelStr = "Unknown: "; + break; + } + char buffer[FORMAT_MSG_BUFFER_SIZE + 1] = { 0 }; + strcpy(buffer, levelStr); + va_list args; + va_start(args, _fmt); + vsnprintf(buffer + strlen(buffer), FORMAT_MSG_BUFFER_SIZE, _fmt, args); + va_end(args); + if (hasbit(dir, DIR_CERR)) + { + std::cerr << buffer << std::endl; + } + if (hasbit(dir, DIR_FILE)) + { + fs << buffer << std::endl; + } +#undef FORMAT_MSG_BUFFER_SIZE +} + +// ض +void Loghelper::redirect(unsigned int _dir, char* _path) +{ + dir = _dir; + if (hasbit(dir, DIR_FILE)) + { + try + { + fs.open(_path, std::ios_base::app); + } + catch (std::ios_base::failure& e) { + dir = DIR_CERR; + log(Level::LV_WARN, "ضlog· %s ʧ", _path); + } + } +} + +// ɸѡȼ +void Loghelper::restrict(unsigned int _levels) +{ + levels = _levels; +} + +void Loghelper::close() +{ + if (!fs.fail()) + fs.close(); + fs.clear(); +} + +#undef hasbit + +#endif + +#endif diff --git a/src/libjin/Utils/endian.h b/src/libjin/Utils/endian.h new file mode 100644 index 0000000..d4c441a --- /dev/null +++ b/src/libjin/Utils/endian.h @@ -0,0 +1,23 @@ +#ifndef JIN_LIL_ENDIAN && JIN_BIG_ENDIAN + +#define JIN_LIL_ENDIAN 2 +#define JIN_BIG_ENDIAN 4 + +#endif + +#ifndef JIN_BYTEORDER +#ifdef __linux__ +#include <endian.h> +#define JIN_BYTEORDER __BYTE_ORDER +#else /* __linux__ */ +#if defined(__hppa__) || \ + defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ + (defined(__MIPS__) && defined(__MISPEB__)) || \ + defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ + defined(__sparc__) +#define JIN_BYTEORDER JIN_BIG_ENDIAN +#else +#define JIN_BYTEORDER JIN_LIL_ENDIAN +#endif +#endif /* __linux__ */ +#endif /* !SDL_BYTEORDER */
\ No newline at end of file diff --git a/src/libjin/Utils/macros.h b/src/libjin/Utils/macros.h new file mode 100644 index 0000000..684e8e8 --- /dev/null +++ b/src/libjin/Utils/macros.h @@ -0,0 +1,16 @@ +#ifndef __JIN_MACROS_H +#define __JIN_MACROS_H +#include <cstring> + +#define implement // ʵֽӿ + +#define shared // ķ + +#define MASK // enum + +#define CALLONCE(call) static char __dummy__=(call, 1) // ֻһ +#define onlyonce // ֻһ + +#define zero(mem) memset(&mem, 0, sizeof(mem)) + +#endif
\ No newline at end of file diff --git a/src/libjin/Utils/unittest.cpp b/src/libjin/Utils/unittest.cpp new file mode 100644 index 0000000..2952b0b --- /dev/null +++ b/src/libjin/Utils/unittest.cpp @@ -0,0 +1,108 @@ +#include "utils.h" +#if UNITTEST + +#include <iostream> +#include <stdio.h> +#include <fstream> +#include "../audio/sdl/source.h" +#include "../audio/sdl/audio.h" + +using namespace jin::audio; +using namespace std; + +int main(int argc, char* argv[]) +{ + SDLAudio* audio = SDLAudio::get(); + audio->init(0); + SDLSource* source = SDLSource::createSource("a.ogg"); + SDLSource* source2 = SDLSource::createSource("a.wav"); + //source->play(); + source2->play(); + source->setLoop(true); + source2->setLoop(true); + int i = 0; + while (true) + { + SDL_Delay(1000); + } + audio->quit(); + return 0; +} + +/* +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <SDL2/SDL.h> + +#include <3rdparty/cmixer/cmixer.h> + +static SDL_mutex* audio_mutex; + +static void lock_handler(cm_Event *e) { + if (e->type == CM_EVENT_LOCK) { + SDL_LockMutex(audio_mutex); + } + if (e->type == CM_EVENT_UNLOCK) { + SDL_UnlockMutex(audio_mutex); + } +} + + +static void audio_callback(void *udata, Uint8 *stream, int size) { + cm_process((cm_Int16*)stream, size / 2); +} + + +int main(int argc, char **argv) { + SDL_AudioDeviceID dev; + SDL_AudioSpec fmt, got; + cm_Source *src; + cm_Source* src2; + + + SDL_Init(SDL_INIT_AUDIO); + audio_mutex = SDL_CreateMutex(); + + memset(&fmt, 0, sizeof(fmt)); + fmt.freq = 44100; + fmt.format = AUDIO_S16; + fmt.channels = 2; + fmt.samples = 1024; + fmt.callback = audio_callback; + + dev = SDL_OpenAudioDevice(NULL, 0, &fmt, &got, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + if (dev == 0) { + fprintf(stderr, "Error: failed to open audio device '%s'\n", SDL_GetError()); + exit(EXIT_FAILURE); + } + + cm_init(got.freq); + cm_set_lock(lock_handler); + cm_set_master_gain(0.5); + + SDL_PauseAudioDevice(dev, 0); + + src = cm_new_source_from_file("a.ogg"); + src2 = cm_new_source_from_file("loop.wav"); + if (!src) { + fprintf(stderr, "Error: failed to create source '%s'\n", cm_get_error()); + exit(EXIT_FAILURE); + } + cm_set_loop(src2, 1); + + cm_play(src); + cm_play(src2); + + printf("Press [return] to exit\n"); + getchar(); + + cm_destroy_source(src); + SDL_CloseAudioDevice(dev); + SDL_Quit(); + + return EXIT_SUCCESS; +} +*/ + +#endif
\ No newline at end of file diff --git a/src/libjin/Utils/utils.h b/src/libjin/Utils/utils.h new file mode 100644 index 0000000..cf0920e --- /dev/null +++ b/src/libjin/Utils/utils.h @@ -0,0 +1,9 @@ +#ifndef __JIN_UTILS_H +#define __JIN_UTILS_H + +#include "macros.h" +#include "endian.h" + +#define UNITTEST 0 + +#endif
\ No newline at end of file |