mesh/texture work

This commit is contained in:
Nishi 2026-06-06 01:04:29 +09:00
commit 5ff134abe4
19 changed files with 376 additions and 22 deletions

View file

@ -11,15 +11,25 @@ namespace fishbone {
#include <fishbone/window.h>
#include <fishbone/meshldr.h>
#include <fishbone/textureldr.h>
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

View file

@ -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

View file

@ -13,5 +13,7 @@
#include <fishbone/base.h>
#include <fishbone/meshldr.h>
#include <fishbone/log.h>
#include <fishbone/math.h>
#include <fishbone/textureldr.h>
#endif

View file

@ -11,6 +11,7 @@
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <fishbone/config.h>

View file

@ -0,0 +1,18 @@
#ifndef __FISHBONE_MATH_H__
#define __FISHBONE_MATH_H__
#include <fishbone/pre.h>
namespace fishbone {
float cot(float x);
};
/* no includes */
namespace fishbone {
float cot(float x);
static double pi = 3.14159265358979323846;
}; // namespace fishbone
#endif

View file

@ -14,6 +14,8 @@ namespace fishbone {
public:
MeshData(fishbone::File* file);
bool good();
std::vector<struct fishbone::Vector3> vertices;
std::vector<struct fishbone::Vector2> texcoords;
std::vector<struct fishbone::Vector3> normals;

View file

@ -23,10 +23,10 @@ namespace fishbone {
void lock();
void unlock();
static const int rate = 44100;
std::vector<fishbone::SoundLoader*> loaders;
std::vector<fishbone::Sound*> sounds;
float position[3];
static const int rate = 44100;
};
}; // namespace fishbone

View file

@ -0,0 +1,26 @@
#ifndef __FISHBONE_TEXLDR_H__
#define __FISHBONE_TEXLDR_H__
#include <fishbone/pre.h>
namespace fishbone {
class TextureData;
};
#include <fishbone/file.h>
namespace fishbone {
class TextureData {
public:
TextureData(fishbone::File* file);
~TextureData();
bool good();
unsigned char* rgba;
int width;
int height;
};
}; // namespace fishbone
#endif

View file

@ -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;

View file

@ -18,6 +18,9 @@ namespace fishbone {
void poll();
void swapBuffer();
int width;
int height;
};
}; // namespace fishbone

View file

@ -1,8 +1,7 @@
#include <fishbone/foundation.h>
fishbone::File* f;
fishbone::MeshData* md;
fishbone::Mesh* m;
fishbone::File* f;
fishbone::Mesh* m;
fishbone::Client::Client(std::unordered_map<std::string, std::vector<std::string>> param) {
this->window = new fishbone::Window("Fishbone", 800, 600);
@ -10,12 +9,22 @@ fishbone::Client::Client(std::unordered_map<std::string, std::vector<std::string
this->mixer = &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();

View file

@ -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<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> 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::vector<struct fishb
glGenBuffers(1, &this->impl->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});
}

View file

@ -1,12 +1,10 @@
#include <fishbone/file.h>
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;
}

5
engine/src/math.cc Normal file
View file

@ -0,0 +1,5 @@
#include <fishbone/foundation.h>
float fishbone::cot(float x) {
return 1.0 / tan(x);
}

View file

@ -1,7 +1,5 @@
#include <fishbone/foundation.h>
#include <iostream>
static std::vector<int> parseFace(std::string s) {
std::vector<int> v;
std::string n = "";
@ -27,6 +25,12 @@ fishbone::MeshData::MeshData(fishbone::File* f) {
std::vector<struct fishbone::Vector3> 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<int> 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<int> 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;
}

View file

@ -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];

23
engine/src/textureldr.cc Normal file
View file

@ -0,0 +1,23 @@
#include <fishbone/foundation.h>
#include <iostream>
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;
}

56
engine/src/types.cc Normal file
View file

@ -0,0 +1,56 @@
#include <fishbone/foundation.h>
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};
}

View file

@ -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() {