From 5ff134abe40a8461ac85c117dfbd972aa993335e Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 6 Jun 2026 01:04:29 +0900 Subject: [PATCH] mesh/texture work --- engine/include/fishbone/draw.h | 20 +++- engine/include/fishbone/file.h | 2 +- engine/include/fishbone/foundation.h | 2 + engine/include/fishbone/machdep.h | 1 + engine/include/fishbone/math.h | 18 ++++ engine/include/fishbone/meshldr.h | 2 + engine/include/fishbone/mixer.h | 2 +- engine/include/fishbone/textureldr.h | 26 +++++ engine/include/fishbone/types.h | 13 +++ engine/include/fishbone/window.h | 3 + engine/src/client.cc | 24 ++++- engine/src/draw/opengl.cc | 137 ++++++++++++++++++++++++++- engine/src/file.cc | 9 +- engine/src/math.cc | 5 + engine/src/meshldr.cc | 52 ++++++++-- engine/src/mixer.cc | 2 +- engine/src/textureldr.cc | 23 +++++ engine/src/types.cc | 56 +++++++++++ engine/src/window/sdl2.cc | 3 + 19 files changed, 377 insertions(+), 23 deletions(-) create mode 100644 engine/include/fishbone/math.h create mode 100644 engine/include/fishbone/textureldr.h create mode 100644 engine/src/math.cc create mode 100644 engine/src/textureldr.cc create mode 100644 engine/src/types.cc diff --git a/engine/include/fishbone/draw.h b/engine/include/fishbone/draw.h index 3855f0e..0d5a9dc 100644 --- a/engine/include/fishbone/draw.h +++ b/engine/include/fishbone/draw.h @@ -11,15 +11,25 @@ namespace fishbone { #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); + 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 use(); }; class Mesh { @@ -38,6 +48,10 @@ namespace fishbone { ~Mesh(); void draw(); + void draw(struct fishbone::Vector3 pos); + void draw(struct fishbone::Vector3 pos, struct fishbone::Vector3 rot); + + fishbone::Texture* texture; }; class Renderer { @@ -47,7 +61,11 @@ namespace fishbone { public: Renderer(fishbone::Window* window); ~Renderer(); + + void prepare(); }; + + static float maxDistance = 64; }; // namespace fishbone #endif diff --git a/engine/include/fishbone/file.h b/engine/include/fishbone/file.h index 4dbf9ce..16b7d8b 100644 --- a/engine/include/fishbone/file.h +++ b/engine/include/fishbone/file.h @@ -21,9 +21,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/foundation.h b/engine/include/fishbone/foundation.h index dfb58fe..27f53fb 100644 --- a/engine/include/fishbone/foundation.h +++ b/engine/include/fishbone/foundation.h @@ -13,5 +13,7 @@ #include #include #include +#include +#include #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..0b1bb83 --- /dev/null +++ b/engine/include/fishbone/math.h @@ -0,0 +1,18 @@ +#ifndef __FISHBONE_MATH_H__ +#define __FISHBONE_MATH_H__ + +#include + +namespace fishbone { + float cot(float x); +}; + +/* no includes */ + +namespace fishbone { + float cot(float x); + + static double pi = 3.14159265358979323846; +}; // namespace fishbone + +#endif diff --git a/engine/include/fishbone/meshldr.h b/engine/include/fishbone/meshldr.h index f38b49f..a32dc18 100644 --- a/engine/include/fishbone/meshldr.h +++ b/engine/include/fishbone/meshldr.h @@ -14,6 +14,8 @@ namespace fishbone { public: MeshData(fishbone::File* file); + bool good(); + std::vector vertices; std::vector texcoords; std::vector normals; 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/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/types.h b/engine/include/fishbone/types.h index 184b9c6..7daadc4 100644 --- a/engine/include/fishbone/types.h +++ b/engine/include/fishbone/types.h @@ -5,11 +5,24 @@ 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; diff --git a/engine/include/fishbone/window.h b/engine/include/fishbone/window.h index 9a9abac..53cd0c0 100644 --- a/engine/include/fishbone/window.h +++ b/engine/include/fishbone/window.h @@ -18,6 +18,9 @@ namespace fishbone { void poll(); void swapBuffer(); + + int width; + int height; }; }; // namespace fishbone diff --git a/engine/src/client.cc b/engine/src/client.cc index 9482306..8009e67 100644 --- a/engine/src/client.cc +++ b/engine/src/client.cc @@ -1,8 +1,7 @@ #include -fishbone::File* f; -fishbone::MeshData* md; -fishbone::Mesh* m; +fishbone::File* f; +fishbone::Mesh* m; fishbone::Client::Client(std::unordered_map> param) { this->window = new fishbone::Window("Fishbone", 800, 600); @@ -10,12 +9,22 @@ fishbone::Client::Client(std::unordered_mapmixer = &this->sounddrv->mixer; this->renderer = new fishbone::Renderer(this->window); + fishbone::MeshData* md; + fishbone::TextureData* td; + f = new fishbone::File("model.obj", "r"); md = new fishbone::MeshData(f); delete f; - m = new fishbone::Mesh(this->renderer, md); + f = new fishbone::File("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() { @@ -24,8 +33,13 @@ fishbone::Client::~Client() { delete this->window; } +float r = 0; + bool fishbone::Client::step() { - m->draw(); + this->renderer->prepare(); + + m->draw((struct fishbone::Vector3){0, 0, 0}, (struct fishbone::Vector3){0, r, 0}); + r++; this->window->swapBuffer(); diff --git a/engine/src/draw/opengl.cc b/engine/src/draw/opengl.cc index 1a47622..e17e526 100644 --- a/engine/src/draw/opengl.cc +++ b/engine/src/draw/opengl.cc @@ -4,7 +4,7 @@ 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); @@ -21,6 +21,10 @@ fishbone::Texture::~Texture() { delete this->impl; } +void fishbone::Texture::use() { + glBindTexture(GL_TEXTURE_2D, this->impl->texture); +} + struct fishbone::Mesh::Impl { GLuint v_vbo; GLuint t_vbo; @@ -34,6 +38,8 @@ struct fishbone::Mesh::Impl { }; 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 float[vertices.size() * 3]; this->impl->texcoords = new float[texcoords.size() * 2]; @@ -44,11 +50,28 @@ void fishbone::Mesh::init(fishbone::Renderer* renderer, std::vectorimpl->t_vbo); glGenBuffers(1, &this->impl->n_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); @@ -81,17 +104,127 @@ void fishbone::Mesh::draw() { glBindBuffer(GL_ARRAY_BUFFER, this->impl->n_vbo); glNormalPointer(GL_FLOAT, 0, nullptr); + glColor3f(1, 1, 1); glEnable(GL_TEXTURE_2D); + if(this->texture != nullptr) this->texture->use(); glDrawArrays(GL_TRIANGLES, 0, this->impl->count); glDisable(GL_TEXTURE_2D); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } +void fishbone::Mesh::draw(struct fishbone::Vector3 pos) { + this->draw(pos, {0, 0, 0}); +} + +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({2, 2, 2}, {0, 0, 0}); } diff --git a/engine/src/file.cc b/engine/src/file.cc index 9cd8301..505456f 100644 --- a/engine/src/file.cc +++ b/engine/src/file.cc @@ -1,12 +1,10 @@ #include fishbone::File::File() { - this->good = true; this->size = 0; } fishbone::File::File(std::string path, std::string type) { - this->good = false; this->size = 0; if(type == "r") { @@ -24,8 +22,6 @@ fishbone::File::File(std::string path, std::string type) { } else { return; } - - this->good = true; } fishbone::File::~File() { @@ -48,3 +44,8 @@ size_t fishbone::File::write(const void* buffer, size_t size) { return size; } + +bool fishbone::File::good() { + if(this->ifs.good() || this->ofs.good()) return true; + return false; +} 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 index 4391fb5..4f491b7 100644 --- a/engine/src/meshldr.cc +++ b/engine/src/meshldr.cc @@ -1,7 +1,5 @@ #include -#include - static std::vector parseFace(std::string s) { std::vector v; std::string n = ""; @@ -27,6 +25,12 @@ fishbone::MeshData::MeshData(fishbone::File* f) { 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') { @@ -49,9 +53,18 @@ fishbone::MeshData::MeshData(fishbone::File* f) { 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]), std::stof(vs[2])}; + fishbone::Vector2 nv = {std::stof(vs[1]), 1 - std::stof(vs[2])}; vt.push_back(nv); } else if(vs[0] == "vn") { @@ -59,12 +72,28 @@ fishbone::MeshData::MeshData(fishbone::File* f) { vn.push_back(nv); } else if(vs[0] == "f") { - for(int i = 1; i < 4; i++) { - std::vector ind = parseFace(vs[i]); + float sc = 0; + float lr = fabs(lm - rm); + float ud = fabs(um - dm); + float bf = fabs(fm - bm); - this->vertices.push_back(v[ind[0]]); - this->texcoords.push_back(ind.size() >= 2 ? vt[ind[1]] : e2); - this->normals.push_back(ind.size() >= 3 ? vn[ind[2]] : e3); + if(sc < lr) sc = lr; + if(sc < ud) sc = ud; + if(sc < bf) sc = bf; + + sc /= 2; + + for(int i = 1; i < 4; i++) { + std::vector ind = parseFace(vs[i]); + struct fishbone::Vector3 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); } } } @@ -74,3 +103,10 @@ fishbone::MeshData::MeshData(fishbone::File* f) { } } } + +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/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/types.cc b/engine/src/types.cc new file mode 100644 index 0000000..6239fc3 --- /dev/null +++ b/engine/src/types.cc @@ -0,0 +1,56 @@ +#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}; +} diff --git a/engine/src/window/sdl2.cc b/engine/src/window/sdl2.cc index e14965e..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() {