diff --git a/client/main.cc b/client/main.cc index f46336b..174db3d 100644 --- a/client/main.cc +++ b/client/main.cc @@ -12,7 +12,9 @@ static void cleanup(int sig){ int main(){ fishbone::Client* client; - std::unordered_map> param; + fishbone::StringArrayMap param; + + param["basedir"] = {"./data", "../data"}; client = new fishbone::Client(param); diff --git a/data/model.obj b/data/model.obj new file mode 100644 index 0000000..18e8c39 --- /dev/null +++ b/data/model.obj @@ -0,0 +1,28 @@ +# Blender 5.0.1 +# www.blender.org +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 0.500000 -0.500000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -0.0000 -1.0000 -0.0000 +vn -0.0000 1.0000 -0.0000 +vt 0.000000 0.000000 +vt 0.000000 1.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +s 0 +usemtl Material +f 1/1/1 2/2/1 4/3/1 3/4/1 +f 3/1/2 4/2/2 8/3/2 7/4/2 +f 7/4/3 8/3/3 6/2/3 5/1/3 +f 5/4/4 6/3/4 2/2/4 1/1/4 +f 3/2/5 7/3/5 5/4/5 1/1/5 +f 8/3/6 4/2/6 2/1/6 6/4/6 diff --git a/data/model.png b/data/model.png new file mode 100644 index 0000000..1ce3321 Binary files /dev/null and b/data/model.png differ diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 4e7fbbd..acdc2e7 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -37,6 +37,7 @@ pkg_add(fishbone sdl2 REQUIRED) set(FISHBONE_SOUND_USE_SDL2 ON) set(FISHBONE_WINDOW_USE_SDL2 ON) set(FISHBONE_THREAD_USE_SDL2 ON) +set(FISHBONE_DRAW_USE_OPENGL ON) configure_file(config.h.in fishbone/config.h) target_include_directories(fishbone PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/engine/config.h.in b/engine/config.h.in index b9e25db..c42dc21 100644 --- a/engine/config.h.in +++ b/engine/config.h.in @@ -4,5 +4,6 @@ #cmakedefine FISHBONE_SOUND_USE_SDL2 #cmakedefine FISHBONE_WINDOW_USE_SDL2 #cmakedefine FISHBONE_THREAD_USE_SDL2 +#cmakedefine FISHBONE_DRAW_USE_OPENGL #endif diff --git a/engine/include/fishbone/base.h b/engine/include/fishbone/base.h new file mode 100644 index 0000000..11910c5 --- /dev/null +++ b/engine/include/fishbone/base.h @@ -0,0 +1,25 @@ +#ifndef __FISHBONE_BASE_H__ +#define __FISHBONE_BASE_H__ + +#include + +namespace fishbone { + class Base; +}; + +#include +#include + +namespace fishbone { + class Base : public fishbone::Logger { + fishbone::StringArrayMap mountpoints; + + public: + Base(fishbone::StringArrayMap param); + + void mount(std::string name, std::string path); + fishbone::File* open(std::string path, std::string mode); + }; +}; // namespace fishbone + +#endif diff --git a/engine/include/fishbone/client.h b/engine/include/fishbone/client.h index e29a7cb..c420fb3 100644 --- a/engine/include/fishbone/client.h +++ b/engine/include/fishbone/client.h @@ -11,19 +11,20 @@ namespace fishbone { #include #include #include +#include namespace fishbone { - class Client { + class Client : public fishbone::Base { public: - Client(std::unordered_map> param); + Client(fishbone::StringArrayMap param); ~Client(); bool step(); - + fishbone::Window* window; fishbone::SoundDriver* sounddrv; - fishbone::Mixer* mixer; - fishbone::Renderer* renderer; + fishbone::Mixer* mixer; + fishbone::Renderer* renderer; }; }; // namespace fishbone diff --git a/engine/include/fishbone/draw.h b/engine/include/fishbone/draw.h index a786e94..d01a57e 100644 --- a/engine/include/fishbone/draw.h +++ b/engine/include/fishbone/draw.h @@ -7,39 +7,89 @@ namespace fishbone { class Texture; class Mesh; class Renderer; -}; +}; // namespace fishbone -/* no includes */ +#include +#include +#include +#include namespace fishbone { class Texture { + void init(fishbone::Renderer* renderer, unsigned char* rgba, int width, int height); + struct Impl; Impl* impl; - public: - Texture(fishbone::Renderer* renderer, unsigned char* rgba, int width, int height); + public: + Texture(fishbone::Renderer* renderer, unsigned char* rgba, int width, int height) { + this->init(renderer, rgba, width, height); + } + Texture(fishbone::Renderer* renderer, fishbone::TextureData* data) { + this->init(renderer, data->rgba, data->width, data->height); + } ~Texture(); + + void begin(); + void end(); }; class Mesh { + void init(fishbone::Renderer* renderer, std::vector vertices, std::vector texcoords, std::vector normals); + struct Impl; Impl* impl; - public: - Mesh(fishbone::Renderer* renderer, std::vector vertices, std::vector texcoords, std::vector normals, std::vector elements); + public: + Mesh(fishbone::Renderer* renderer, std::vector vertices, std::vector texcoords, std::vector normals) { + this->init(renderer, vertices, texcoords, normals); + } + Mesh(fishbone::Renderer* renderer, fishbone::MeshData* data) { + this->init(renderer, data->vertices, data->texcoords, data->normals); + } ~Mesh(); void draw(); + void draw(struct fishbone::Vector3 pos); + void draw(struct fishbone::Vector3 pos, struct fishbone::Vector3 rot); + + fishbone::Texture* texture; }; class Renderer { struct Impl; Impl* impl; - public: - Renderer(); + public: + Renderer(fishbone::Window* window); ~Renderer(); + + void prepare(); + void quad(std::vector vertices, std::vector texcoords, std::vector normals) { + std::vector v; + std::vector t; + std::vector n; + + v = fishbone::quadToTriangle(vertices); + t = fishbone::quadToTriangle(texcoords); + n = fishbone::quadToTriangle(normals); + + this->triangle(v, t, n); + } + void triangle(std::vector vertices, std::vector texcoords, std::vector normals); + void quad(std::vector vertices, std::vector texcoords) { + std::vector v; + std::vector t; + + v = fishbone::quadToTriangle(vertices); + t = fishbone::quadToTriangle(texcoords); + + this->triangle(v, t); + } + void triangle(std::vector vertices, std::vector texcoords); }; -}; + + static float maxDistance = 64; +}; // namespace fishbone #endif diff --git a/engine/include/fishbone/file.h b/engine/include/fishbone/file.h index 4dbf9ce..ff5e840 100644 --- a/engine/include/fishbone/file.h +++ b/engine/include/fishbone/file.h @@ -13,6 +13,7 @@ namespace fishbone { class File { std::ifstream ifs; std::ofstream ofs; + bool opened; public: File(); @@ -21,9 +22,9 @@ namespace fishbone { virtual size_t read(void* buffer, size_t size); virtual size_t write(const void* buffer, size_t size); + bool good(); size_t size; - bool good; }; }; // namespace fishbone diff --git a/engine/include/fishbone/filesystem.h b/engine/include/fishbone/filesystem.h new file mode 100644 index 0000000..fa1ded1 --- /dev/null +++ b/engine/include/fishbone/filesystem.h @@ -0,0 +1,16 @@ +#ifndef __FISHBONE_FILESYSTEM_H__ +#define __FISHBONE_FILESYSTEM_H__ + +#include + +namespace fishbone { + bool exists(std::string path); +}; + +/* no includes */ + +namespace fishbone { + bool exists(std::string path); +}; + +#endif diff --git a/engine/include/fishbone/foundation.h b/engine/include/fishbone/foundation.h index 85f859e..d2b7bcd 100644 --- a/engine/include/fishbone/foundation.h +++ b/engine/include/fishbone/foundation.h @@ -10,5 +10,11 @@ #include #include #include +#include +#include +#include +#include +#include +#include #endif diff --git a/engine/include/fishbone/log.h b/engine/include/fishbone/log.h new file mode 100644 index 0000000..83a0978 --- /dev/null +++ b/engine/include/fishbone/log.h @@ -0,0 +1,35 @@ +#ifndef __FISHBONE_LOG_H__ +#define __FISHBONE_LOG_H__ + +#include + +namespace fishbone { + class Logger; +}; + +/* no includes */ + +namespace fishbone { + class Logger { + enum LoggerLevel { + Log = 0, + Info, + Warn, + Error + }; + + void init(std::string path); + + std::ofstream ofs; + + public: + Logger(); + Logger(std::string path); + ~Logger(); + + void log(std::string arg); + void log(int level, std::string arg); + }; +}; // namespace fishbone + +#endif diff --git a/engine/include/fishbone/machdep.h b/engine/include/fishbone/machdep.h index 681fa77..91723e7 100644 --- a/engine/include/fishbone/machdep.h +++ b/engine/include/fishbone/machdep.h @@ -11,6 +11,7 @@ #include #include #include +#include #include diff --git a/engine/include/fishbone/math.h b/engine/include/fishbone/math.h new file mode 100644 index 0000000..838640f --- /dev/null +++ b/engine/include/fishbone/math.h @@ -0,0 +1,41 @@ +#ifndef __FISHBONE_MATH_H__ +#define __FISHBONE_MATH_H__ + +#include + +namespace fishbone { + float cot(float x); + template + std::vector quadToTriangle(std::vector v); +}; // namespace fishbone + +/* no includes */ + +namespace fishbone { + float cot(float x); + template + std::vector quadToTriangle(std::vector v) { + std::vector r; + + /** + * 1-4 + * |\| + * 2-3 + */ + for(int i = 0; i < v.size(); i += 4) { + r.push_back(v[i + 0]); + r.push_back(v[i + 1]); + r.push_back(v[i + 2]); + + r.push_back(v[i + 2]); + r.push_back(v[i + 3]); + r.push_back(v[i + 0]); + } + + return r; + } + + static double pi = 3.14159265358979323846; +}; // namespace fishbone + +#endif diff --git a/engine/include/fishbone/meshldr.h b/engine/include/fishbone/meshldr.h new file mode 100644 index 0000000..a32dc18 --- /dev/null +++ b/engine/include/fishbone/meshldr.h @@ -0,0 +1,25 @@ +#ifndef __FISHBONE_MESHLDR_H__ +#define __FISHBONE_MESHLDR_H__ + +#include + +namespace fishbone { + class MeshData; +}; + +#include + +namespace fishbone { + class MeshData { + public: + MeshData(fishbone::File* file); + + bool good(); + + std::vector vertices; + std::vector texcoords; + std::vector normals; + }; +}; // namespace fishbone + +#endif diff --git a/engine/include/fishbone/mixer.h b/engine/include/fishbone/mixer.h index 23330af..87d4fb5 100644 --- a/engine/include/fishbone/mixer.h +++ b/engine/include/fishbone/mixer.h @@ -23,10 +23,10 @@ namespace fishbone { void lock(); void unlock(); - static const int rate = 44100; std::vector loaders; std::vector sounds; float position[3]; + static const int rate = 44100; }; }; // namespace fishbone diff --git a/engine/include/fishbone/resource.h b/engine/include/fishbone/resource.h index a995f15..8efa342 100644 --- a/engine/include/fishbone/resource.h +++ b/engine/include/fishbone/resource.h @@ -12,10 +12,10 @@ namespace fishbone { namespace fishbone { class Resource { public: - fishbone::File* open(std::string path); - Resource(std::string path); ~Resource(); + + fishbone::File* open(std::string path); }; }; // namespace fishbone diff --git a/engine/include/fishbone/sound.h b/engine/include/fishbone/sound.h index 1277ec5..4ee2f0d 100644 --- a/engine/include/fishbone/sound.h +++ b/engine/include/fishbone/sound.h @@ -55,12 +55,16 @@ namespace fishbone { class SoundLoader { public: - SoundLoader(){}; - ~SoundLoader(){}; + SoundLoader() {}; + ~SoundLoader() {}; - virtual Sound* open(Mixer* mixer, void* buffer, size_t size){return nullptr;}; - virtual int read(Sound* sound, short* buffer, size_t frames){return 0;}; - virtual void seek(Sound* sound, size_t pos){}; + virtual Sound* open(Mixer* mixer, void* buffer, size_t size) { + return nullptr; + }; + virtual int read(Sound* sound, short* buffer, size_t frames) { + return 0; + }; + virtual void seek(Sound* sound, size_t pos) {}; }; class Sound { diff --git a/engine/include/fishbone/textureldr.h b/engine/include/fishbone/textureldr.h new file mode 100644 index 0000000..694f806 --- /dev/null +++ b/engine/include/fishbone/textureldr.h @@ -0,0 +1,26 @@ +#ifndef __FISHBONE_TEXLDR_H__ +#define __FISHBONE_TEXLDR_H__ + +#include + +namespace fishbone { + class TextureData; +}; + +#include + +namespace fishbone { + class TextureData { + public: + TextureData(fishbone::File* file); + ~TextureData(); + + bool good(); + + unsigned char* rgba; + int width; + int height; + }; +}; // namespace fishbone + +#endif diff --git a/engine/include/fishbone/time.h b/engine/include/fishbone/time.h index cd7e6a9..34ed080 100644 --- a/engine/include/fishbone/time.h +++ b/engine/include/fishbone/time.h @@ -7,7 +7,7 @@ namespace fishbone { using AccurateClock = std::chrono::time_point; fishbone::AccurateClock accurateTime(); -}; +}; // namespace fishbone /* no includes */ diff --git a/engine/include/fishbone/types.h b/engine/include/fishbone/types.h index 9d01009..30c15f6 100644 --- a/engine/include/fishbone/types.h +++ b/engine/include/fishbone/types.h @@ -5,15 +5,40 @@ namespace fishbone { struct Vector2 { + struct fishbone::Vector2 operator+(struct fishbone::Vector2 v) const; + struct fishbone::Vector2 operator-(struct fishbone::Vector2 v) const; + + float length(); + struct fishbone::Vector2 normalize(); + float x; float y; }; struct Vector3 { + struct fishbone::Vector3 operator+(struct fishbone::Vector3 v) const; + struct fishbone::Vector3 operator-(struct fishbone::Vector3 v) const; + struct fishbone::Vector3 operator*(struct fishbone::Vector3 v) const; + + float length(); + struct fishbone::Vector3 normalize(); + float x; float y; float z; }; -}; + + struct Quaternion { + struct fishbone::Quaternion operator+(struct fishbone::Quaternion q) const; + struct fishbone::Quaternion operator-(struct fishbone::Quaternion q) const; + + float w; + float x; + float y; + float z; + }; + + using StringArrayMap = std::unordered_map>; +}; // namespace fishbone #endif diff --git a/engine/include/fishbone/window.h b/engine/include/fishbone/window.h index 0846a75..53cd0c0 100644 --- a/engine/include/fishbone/window.h +++ b/engine/include/fishbone/window.h @@ -17,6 +17,10 @@ namespace fishbone { ~Window(); void poll(); + void swapBuffer(); + + int width; + int height; }; }; // namespace fishbone diff --git a/engine/src/base.cc b/engine/src/base.cc new file mode 100644 index 0000000..f657a79 --- /dev/null +++ b/engine/src/base.cc @@ -0,0 +1,52 @@ +#include + +fishbone::Base::Base(fishbone::StringArrayMap param) { + for(auto i = param.begin(); i != param.end(); i++) { + if(i->first == "basedir") { + for(int j = 0; j < i->second.size(); j++) { + this->mount("base", i->second[j]); + } + } + } +} + +void fishbone::Base::mount(std::string name, std::string path) { + if(this->mountpoints.find(name) == this->mountpoints.end()) this->mountpoints[name] = {}; + + this->mountpoints[name].push_back(path); +} + +fishbone::File* fishbone::Base::open(std::string path, std::string mode) { + fishbone::File* f = nullptr; + + for(int i = 0; i < path.size() - 1; i++) { + if(path.substr(i, 2) == ":/") { + std::string p = path.substr(i + 1); + std::string k = path.substr(0, i); + + if(this->mountpoints.find(k) != this->mountpoints.end()) { + for(int j = 0; j < this->mountpoints[k].size(); j++) { + f = new fishbone::File(this->mountpoints[k][j] + p, mode); + + if(!f->good()) { + delete f; + f = nullptr; + } + + if(f != nullptr && f->good()) break; + } + } + + break; + } + } + + if(f == nullptr) f = new fishbone::File(path, mode); + + if(f != nullptr && !f->good()) { + delete f; + f = nullptr; + } + + return f; +} diff --git a/engine/src/client.cc b/engine/src/client.cc index bc17717..08f64a1 100644 --- a/engine/src/client.cc +++ b/engine/src/client.cc @@ -1,18 +1,48 @@ #include -fishbone::Client::Client(std::unordered_map> param){ - this->window = new fishbone::Window("Fishbone", 800, 600); +fishbone::File* f; +fishbone::Mesh* m; + +fishbone::Client::Client(fishbone::StringArrayMap param) + : fishbone::Base::Base(param) { + this->window = new fishbone::Window("Fishbone", 800, 600); this->sounddrv = new fishbone::SoundDriver(); - this->mixer = &this->sounddrv->mixer; - this->renderer = new fishbone::Renderer(); + this->mixer = &this->sounddrv->mixer; + this->renderer = new fishbone::Renderer(this->window); + + fishbone::MeshData* md; + fishbone::TextureData* td; + + f = this->open("base:/model.obj", "r"); + md = new fishbone::MeshData(f); + delete f; + + f = this->open("base:/model.png", "r"); + td = new fishbone::TextureData(f); + delete f; + + m = new fishbone::Mesh(this->renderer, md); + m->texture = new fishbone::Texture(this->renderer, td); + + delete md; + delete td; } -fishbone::Client::~Client(){ +fishbone::Client::~Client() { delete this->renderer; delete this->sounddrv; delete this->window; } -bool fishbone::Client::step(){ +float r = 0; + +bool fishbone::Client::step() { + this->renderer->prepare(); + + m->draw((struct fishbone::Vector3){0, 0, 0}, (struct fishbone::Vector3){r, r, r}); + r += 30.0 / 60; + + this->window->swapBuffer(); + return true; } diff --git a/engine/src/draw/opengl.cc b/engine/src/draw/opengl.cc index 0a0c187..9289620 100644 --- a/engine/src/draw/opengl.cc +++ b/engine/src/draw/opengl.cc @@ -1,12 +1,14 @@ +#include +#ifdef FISHBONE_DRAW_USE_OPENGL #include struct fishbone::Texture::Impl { GLuint texture; }; -fishbone::Texture::Texture(fishbone::Renderer* renderer, unsigned char* rgba, int width, int height){ +void fishbone::Texture::init(fishbone::Renderer* renderer, unsigned char* rgba, int width, int height) { this->impl = new struct fishbone::Texture::Impl(); - + glGenTextures(1, &this->impl->texture); glBindTexture(GL_TEXTURE_2D, this->impl->texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba); @@ -15,70 +17,88 @@ fishbone::Texture::Texture(fishbone::Renderer* renderer, unsigned char* rgba, in glBindTexture(GL_TEXTURE_2D, 0); } -fishbone::Texture::~Texture(){ +fishbone::Texture::~Texture() { glDeleteTextures(1, &this->impl->texture); delete this->impl; } +void fishbone::Texture::begin() { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, this->impl->texture); +} + +void fishbone::Texture::end() { + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); +} + struct fishbone::Mesh::Impl { GLuint v_vbo; GLuint t_vbo; GLuint n_vbo; - GLuint e_vbo; - float* vertices; - float* texcoords; - float* normals; - int* elements; + GLfloat* vertices; + GLfloat* texcoords; + GLfloat* normals; int count; }; -fishbone::Mesh::Mesh(fishbone::Renderer* renderer, std::vector vertices, std::vector texcoords, std::vector normals, std::vector elements){ - this->impl = new struct fishbone::Mesh::Impl(); - this->impl->vertices = new float[vertices.size() * 3]; - this->impl->texcoords = new float[texcoords.size() * 2]; - this->impl->normals = new float[normals.size() * 3]; - this->impl->elements = new int[elements.size()]; - this->impl->count = elements.size(); +void fishbone::Mesh::init(fishbone::Renderer* renderer, std::vector vertices, std::vector texcoords, std::vector normals) { + this->texture = nullptr; + + this->impl = new struct fishbone::Mesh::Impl(); + this->impl->vertices = new GLfloat[vertices.size() * 3]; + this->impl->texcoords = new GLfloat[texcoords.size() * 2]; + this->impl->normals = new GLfloat[normals.size() * 3]; + this->impl->count = vertices.size(); glGenBuffers(1, &this->impl->v_vbo); glGenBuffers(1, &this->impl->t_vbo); glGenBuffers(1, &this->impl->n_vbo); - glGenBuffers(1, &this->impl->e_vbo); + + for(int i = 0; i < vertices.size(); i++) { + this->impl->vertices[i * 3 + 0] = vertices[i].x; + this->impl->vertices[i * 3 + 1] = vertices[i].y; + this->impl->vertices[i * 3 + 2] = vertices[i].z; + } + + for(int i = 0; i < texcoords.size(); i++) { + this->impl->texcoords[i * 2 + 0] = texcoords[i].x; + this->impl->texcoords[i * 2 + 1] = texcoords[i].y; + } + + for(int i = 0; i < normals.size(); i++) { + this->impl->normals[i * 3 + 0] = normals[i].x; + this->impl->normals[i * 3 + 1] = normals[i].y; + this->impl->normals[i * 3 + 2] = normals[i].z; + } glBindBuffer(GL_ARRAY_BUFFER, this->impl->v_vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float) * 3, this->impl->vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, this->impl->t_vbo); - glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(float) * 3, this->impl->texcoords, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(float) * 2, this->impl->texcoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, this->impl->n_vbo); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float) * 3, this->impl->normals, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->impl->e_vbo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements.size() * sizeof(int), this->impl->elements, GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } -fishbone::Mesh::~Mesh(){ - glDeleteBuffers(1, &this->impl->e_vbo); +fishbone::Mesh::~Mesh() { glDeleteBuffers(1, &this->impl->n_vbo); glDeleteBuffers(1, &this->impl->t_vbo); glDeleteBuffers(1, &this->impl->v_vbo); - delete[] this->impl->elements; delete[] this->impl->normals; delete[] this->impl->texcoords; delete[] this->impl->vertices; delete this->impl; } -void fishbone::Mesh::draw(){ +void fishbone::Mesh::draw() { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); @@ -92,18 +112,197 @@ void fishbone::Mesh::draw(){ glBindBuffer(GL_ARRAY_BUFFER, this->impl->n_vbo); glNormalPointer(GL_FLOAT, 0, nullptr); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->impl->e_vbo); - glEnable(GL_TEXTURE_2D); - glDrawElements(GL_TRIANGLES, this->impl->count, GL_UNSIGNED_INT, nullptr); - glDisable(GL_TEXTURE_2D); + glColor3f(1, 1, 1); + if(this->texture != nullptr) this->texture->begin(); + glDrawArrays(GL_TRIANGLES, 0, this->impl->count); + if(this->texture != nullptr) this->texture->end(); + + glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } -fishbone::Renderer::Renderer(){ +void fishbone::Mesh::draw(struct fishbone::Vector3 pos) { + this->draw(pos, {0, 0, 0}); } -fishbone::Renderer::~Renderer(){ +void fishbone::Mesh::draw(struct fishbone::Vector3 pos, struct fishbone::Vector3 rot) { + glPushMatrix(); + glTranslatef(pos.x, pos.y, pos.z); + glRotatef(rot.x, 1, 0, 0); + glRotatef(rot.y, 0, 1, 0); + glRotatef(rot.z, 0, 0, 1); + + this->draw(); + + glPopMatrix(); } + +struct fishbone::Renderer::Impl { + fishbone::Window* window; +}; + +static void cameraPerspective(float width, float height) { + float aspect; + float f; + GLdouble matrix[16]; + float fovy = 60.0; + float znear = 0.01; + float zfar = fishbone::maxDistance; + + aspect = width / height; + f = fishbone::cot(fovy / 180 * fishbone::pi / 2); + + for(int i = 0; i < 16; i++) matrix[i] = 0; + matrix[4 * 0 + 0] = f / aspect; + matrix[4 * 1 + 1] = f; + matrix[4 * 2 + 2] = (zfar + znear) / (znear - zfar); + matrix[4 * 3 + 2] = ((GLdouble)2 * zfar * znear) / (znear - zfar); + matrix[4 * 2 + 3] = -1; + + glMultMatrixd(matrix); +} + +static void lookAt(fishbone::Vector3 camera, fishbone::Vector3 look_at) { + GLdouble matrix[16]; + fishbone::Vector3 f; + fishbone::Vector3 up; + fishbone::Vector3 s; + fishbone::Vector3 u; + + f = (look_at - camera).normalize(); + + up.x = 0; + up.y = 1; + up.z = 0; + up = up.normalize(); + + s = (f * up).normalize(); + + u = s * f; + + for(int i = 0; i < 16; i++) matrix[i] = 0; + matrix[4 * 0 + 0] = s.x; + matrix[4 * 1 + 0] = s.y; + matrix[4 * 2 + 0] = s.z; + matrix[4 * 0 + 1] = u.x; + matrix[4 * 1 + 1] = u.y; + matrix[4 * 2 + 1] = u.z; + matrix[4 * 0 + 2] = -f.x; + matrix[4 * 1 + 2] = -f.y; + matrix[4 * 2 + 2] = -f.z; + matrix[4 * 3 + 3] = 1; + + glMultMatrixd(matrix); + glTranslated(-camera.x, -camera.y, -camera.z); +} + +fishbone::Renderer::Renderer(fishbone::Window* window) { + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_BLEND); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glLightfv(GL_LIGHT0, GL_POSITION, (GLfloat[]){0, -1, 0, 1}); + + this->impl = new struct fishbone::Renderer::Impl(); + this->impl->window = window; +} + +fishbone::Renderer::~Renderer() { + delete this->impl; +} + +void fishbone::Renderer::prepare() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + cameraPerspective(this->impl->window->width, this->impl->window->height); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + lookAt({4, 4, 4}, {0, 0, 0}); +} + +void fishbone::Renderer::triangle(std::vector vertices, std::vector texcoords, std::vector normals) { + GLfloat* v = new GLfloat[vertices.size() * 3]; + GLfloat* t = new GLfloat[texcoords.size() * 2]; + GLfloat* n = new GLfloat[normals.size() * 3]; + + for(int i = 0; i < vertices.size(); i++) { + v[i * 3 + 0] = vertices[i].x; + v[i * 3 + 1] = vertices[i].y; + v[i * 3 + 2] = vertices[i].z; + } + + for(int i = 0; i < texcoords.size(); i++) { + t[i * 2 + 0] = texcoords[i].x; + t[i * 2 + 1] = texcoords[i].y; + } + + for(int i = 0; i < normals.size(); i++) { + n[i * 3 + 0] = normals[i].x; + n[i * 3 + 1] = normals[i].y; + n[i * 3 + 2] = normals[i].z; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, v); + glTexCoordPointer(2, GL_FLOAT, 0, t); + glNormalPointer(GL_FLOAT, 0, n); + + glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] n; + delete[] t; + delete[] v; +} + +void fishbone::Renderer::triangle(std::vector vertices, std::vector texcoords) { + GLfloat* v = new GLfloat[vertices.size() * 2]; + GLfloat* t = new GLfloat[texcoords.size() * 2]; + + for(int i = 0; i < vertices.size(); i++) { + v[i * 2 + 0] = vertices[i].x; + v[i * 2 + 1] = vertices[i].y; + } + + for(int i = 0; i < texcoords.size(); i++) { + t[i * 2 + 0] = texcoords[i].x; + t[i * 2 + 1] = texcoords[i].y; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glVertexPointer(2, GL_FLOAT, 0, v); + glTexCoordPointer(2, GL_FLOAT, 0, t); + + glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] t; + delete[] v; +} +#endif diff --git a/engine/src/file.cc b/engine/src/file.cc index fce8a35..2c7f35c 100644 --- a/engine/src/file.cc +++ b/engine/src/file.cc @@ -1,13 +1,12 @@ #include -fishbone::File::File(){ - this->good = true; +fishbone::File::File() { this->size = 0; } fishbone::File::File(std::string path, std::string type) { - this->good = false; - this->size = 0; + this->size = 0; + this->opened = false; if(type == "r") { this->ifs = std::ifstream(path, std::ios::binary); @@ -25,7 +24,7 @@ fishbone::File::File(std::string path, std::string type) { return; } - this->good = true; + this->opened = true; } fishbone::File::~File() { @@ -48,3 +47,8 @@ size_t fishbone::File::write(const void* buffer, size_t size) { return size; } + +bool fishbone::File::good() { + if(this->opened) return true; + return false; +} diff --git a/engine/src/filesystem.cc b/engine/src/filesystem.cc new file mode 100644 index 0000000..dbdd7d9 --- /dev/null +++ b/engine/src/filesystem.cc @@ -0,0 +1,11 @@ +#include + +#include + +bool fishbone::exists(std::string path) { + struct stat s; + + if(stat(path.c_str(), &s) == 0) return true; + + return false; +} diff --git a/engine/src/log.cc b/engine/src/log.cc new file mode 100644 index 0000000..433e1ad --- /dev/null +++ b/engine/src/log.cc @@ -0,0 +1,25 @@ +#include + +void fishbone::Logger::init(std::string path) { + this->ofs = std::ofstream(path, std::ios_base::app); +} + +fishbone::Logger::Logger() { + this->init("log.txt"); +} + +fishbone::Logger::Logger(std::string path) { + this->init(path); +} + +fishbone::Logger::~Logger() { + this->ofs.close(); +} + +void fishbone::Logger::log(std::string arg) { + this->log(fishbone::Logger::Info, arg); +} + +void fishbone::Logger::log(int level, std::string arg) { + this->ofs << "" + arg << std::endl; +} diff --git a/engine/src/math.cc b/engine/src/math.cc new file mode 100644 index 0000000..c341b23 --- /dev/null +++ b/engine/src/math.cc @@ -0,0 +1,5 @@ +#include + +float fishbone::cot(float x) { + return 1.0 / tan(x); +} diff --git a/engine/src/meshldr.cc b/engine/src/meshldr.cc new file mode 100644 index 0000000..750699f --- /dev/null +++ b/engine/src/meshldr.cc @@ -0,0 +1,128 @@ +#include + +static std::vector parseFace(std::string s) { + std::vector v; + std::string n = ""; + + for(int i = 0; i < s.size(); i++) { + if(s[i] == '/') { + v.push_back(std::stoi(n)); + n = ""; + } else { + n += s[i]; + } + } + if(n.size() > 0) v.push_back(std::stoi(n)); + + return v; +} + +fishbone::MeshData::MeshData(fishbone::File* f) { + char c; + std::string l = ""; + std::vector v; + std::vector vt; + std::vector vn; + fishbone::Vector2 e2 = {0, 0}; + fishbone::Vector3 e3 = {0, 0, 0}; + float lm = 0; /* leftmost */ + float rm = 0; /* rightmost */ + float um = 0; /* upmost */ + float dm = 0; /* downmost */ + float fm = 0; /* frontmost */ + float bm = 0; /* backmost */ + + while(f->read(&c, 1) == 1) { + if(c == '\n') { + if(l.size() == 0) { + } else if(l[0] == '#') { + } else { + std::vector vs; + std::string n = ""; + + for(int i = 0; i < l.size(); i++) { + if(l[i] == ' ') { + vs.push_back(n); + n = ""; + } else { + n += l[i]; + } + } + if(n.size() > 0) vs.push_back(n); + + if(vs[0] == "v") { + fishbone::Vector3 nv = {std::stof(vs[1]), std::stof(vs[2]), std::stof(vs[3])}; + + if(lm > nv.x) lm = nv.x; + if(rm < nv.x) rm = nv.x; + + if(dm > nv.y) dm = nv.y; + if(um < nv.y) um = nv.y; + + if(fm > nv.z) fm = nv.z; + if(bm < nv.z) bm = nv.z; + + v.push_back(nv); + } else if(vs[0] == "vt") { + fishbone::Vector2 nv = {std::stof(vs[1]), 1 - std::stof(vs[2])}; + + vt.push_back(nv); + } else if(vs[0] == "vn") { + fishbone::Vector3 nv = {std::stof(vs[1]), std::stof(vs[2]), std::stof(vs[3])}; + + vn.push_back(nv); + } else if(vs[0] == "f") { + float sc = 0; + float lr = fabs(lm - rm); + float ud = fabs(um - dm); + float bf = fabs(fm - bm); + std::vector ind; + struct fishbone::Vector3 v3; + + if(sc < lr) sc = lr; + if(sc < ud) sc = ud; + if(sc < bf) sc = bf; + + sc /= 2; + +#define PUSH(i) \ + ind = parseFace(vs[i]); \ + v3 = v[ind[0] - 1]; \ +\ + v3.x /= sc; \ + v3.y /= sc; \ + v3.z /= sc; \ +\ + this->vertices.push_back(v3); \ + this->texcoords.push_back(ind.size() >= 2 ? vt[ind[1] - 1] : e2); \ + this->normals.push_back(ind.size() >= 3 ? vn[ind[2] - 1] : e3); + + for(int i = 1; i < 4; i++) { + PUSH(i); + } + + /* If it's quad... + * 1-4 + * |\| + * 2-3 + */ + if(vs.size() == 5) { + PUSH(3); + PUSH(4); + PUSH(1); + } + } + } + l = ""; + } else if(c != '\r') { + l += c; + } + } +} + +bool fishbone::MeshData::good() { + if(this->vertices.size() == 0) return false; + if(this->texcoords.size() == 0) return false; + if(this->normals.size() == 0) return false; + return true; +} diff --git a/engine/src/mixer.cc b/engine/src/mixer.cc index 9b58af1..7a78019 100644 --- a/engine/src/mixer.cc +++ b/engine/src/mixer.cc @@ -106,7 +106,7 @@ fishbone::Sound* fishbone::Mixer::open(const char* path) { unsigned char* buffer; fishbone::Sound* snd; - if(!f.good) return nullptr; + if(!f.good()) return nullptr; buffer = new unsigned char[f.size]; diff --git a/engine/src/physics.cc b/engine/src/physics.cc new file mode 100644 index 0000000..10e9255 --- /dev/null +++ b/engine/src/physics.cc @@ -0,0 +1 @@ +#include diff --git a/engine/src/textureldr.cc b/engine/src/textureldr.cc new file mode 100644 index 0000000..068bce6 --- /dev/null +++ b/engine/src/textureldr.cc @@ -0,0 +1,23 @@ +#include + +#include + +fishbone::TextureData::TextureData(fishbone::File* f) { + unsigned char* buf = new unsigned char[f->size]; + int ch; + + f->read(buf, f->size); + + this->rgba = stbi_load_from_memory(buf, f->size, &this->width, &this->height, &ch, 4); + + delete[] buf; +} + +fishbone::TextureData::~TextureData() { + if(this->rgba != nullptr) free(this->rgba); +} + +bool fishbone::TextureData::good() { + if(this->rgba == nullptr) return false; + return true; +} diff --git a/engine/src/time.cc b/engine/src/time.cc index fdf52c4..1046608 100644 --- a/engine/src/time.cc +++ b/engine/src/time.cc @@ -1,5 +1,5 @@ #include -fishbone::AccurateClock fishbone::accurateTime(){ +fishbone::AccurateClock fishbone::accurateTime() { return std::chrono::high_resolution_clock::now(); } diff --git a/engine/src/types.cc b/engine/src/types.cc new file mode 100644 index 0000000..b445192 --- /dev/null +++ b/engine/src/types.cc @@ -0,0 +1,64 @@ +#include + +struct fishbone::Vector2 fishbone::Vector2::operator+(struct fishbone::Vector2 v) const { + return {this->x + v.x, this->y + v.y}; +} + +struct fishbone::Vector2 fishbone::Vector2::operator-(struct fishbone::Vector2 v) const { + return {this->x - v.x, this->y - v.y}; +} + +float fishbone::Vector2::length() { + return sqrt(this->x * this->x + this->y * this->y); +} + +struct fishbone::Vector2 fishbone::Vector2::normalize() { + float l = this->length(); + + if(l > 0) { + l = 1 / l; + } else { + l = 0; + } + + return {this->x * l, this->y * l}; +} + +struct fishbone::Vector3 fishbone::Vector3::operator+(struct fishbone::Vector3 v) const { + return {this->x + v.x, this->y + v.y, this->z + v.z}; +} + +struct fishbone::Vector3 fishbone::Vector3::operator-(struct fishbone::Vector3 v) const { + return {this->x - v.x, this->y - v.y, this->z - v.z}; +} + +struct fishbone::Vector3 fishbone::Vector3::operator*(struct fishbone::Vector3 v) const { + return { + this->y * v.z - this->z * v.y, + this->z * v.x - this->x * v.z, + this->x * v.y - this->y * v.x}; +} + +float fishbone::Vector3::length() { + return sqrt(this->x * this->x + this->y * this->y + this->z * this->z); +} + +struct fishbone::Vector3 fishbone::Vector3::normalize() { + float l = this->length(); + + if(l > 0) { + l = 1 / l; + } else { + l = 0; + } + + return {this->x * l, this->y * l, this->z * l}; +} + +struct fishbone::Quaternion fishbone::Quaternion::operator+(struct fishbone::Quaternion q) const { + return {this->w + q.w, this->x + q.x, this->y + q.y, this->z + q.z}; +} + +struct fishbone::Quaternion fishbone::Quaternion::operator-(struct fishbone::Quaternion q) const { + return {this->w - q.w, this->x - q.x, this->y - q.y, this->z - q.z}; +} diff --git a/engine/src/window/sdl2.cc b/engine/src/window/sdl2.cc index 9264184..927216b 100644 --- a/engine/src/window/sdl2.cc +++ b/engine/src/window/sdl2.cc @@ -20,6 +20,9 @@ fishbone::Window::Window(std::string title, int width, int height) { this->impl->ctx = SDL_GL_CreateContext(this->impl->window); gladLoadGL(); + + this->width = width; + this->height = height; } fishbone::Window::~Window() { @@ -28,10 +31,14 @@ fishbone::Window::~Window() { delete this->impl; } -void fishbone::Window::poll(){ +void fishbone::Window::poll() { SDL_Event ev; - while(SDL_PollEvent(&ev)){ + while(SDL_PollEvent(&ev)) { } } + +void fishbone::Window::swapBuffer() { + SDL_GL_SwapWindow(this->impl->window); +} #endif