Compare commits

..

7 commits

Author SHA1 Message Date
2a4c8de8d7 2d 2026-06-10 01:10:55 +09:00
112a8f568b things 2026-06-06 22:30:58 +09:00
748d52c9c9 add quaternion 2026-06-06 01:28:10 +09:00
c6ce943f61 quad obj support 2026-06-06 01:18:49 +09:00
be5e710521 stuff 2026-06-06 01:07:19 +09:00
5ff134abe4 mesh/texture work 2026-06-06 01:04:35 +09:00
03b8658666 wip 2026-06-05 21:43:30 +09:00
45 changed files with 918 additions and 289 deletions

View file

@ -12,7 +12,9 @@ static void cleanup(int sig){
int main(){
fishbone::Client* client;
std::unordered_map<std::string, std::vector<std::string>> param;
fishbone::StringArrayMap param;
param["basedir"] = {"./data", "../data"};
client = new fishbone::Client(param);

28
data/model.obj Normal file
View file

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

BIN
data/model.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

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

View file

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

View file

@ -0,0 +1,25 @@
#ifndef __FISHBONE_BASE_H__
#define __FISHBONE_BASE_H__
#include <fishbone/pre.h>
namespace fishbone {
class Base;
};
#include <fishbone/log.h>
#include <fishbone/file.h>
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

View file

@ -5,27 +5,18 @@
namespace fishbone {
class Client;
class ResourceResolver;
}; // namespace fishbone
};
#include <fishbone/sound.h>
#include <fishbone/window.h>
#include <fishbone/mixer.h>
#include <fishbone/draw.h>
#include <fishbone/logger.h>
#include <fishbone/base.h>
namespace fishbone {
class BaseEngine : public Logger {
protected:
ResourceResolver* resourceResolver;
class Client : public fishbone::Base {
public:
ResourceResolver* getResourceResolver();
};
class Client : public BaseEngine {
public:
Client(std::unordered_map<std::string, std::vector<std::string>> param);
Client(fishbone::StringArrayMap param);
~Client();
bool step();

View file

@ -7,39 +7,89 @@ namespace fishbone {
class Texture;
class Mesh;
class Renderer;
};
}; // namespace fishbone
/* no includes */
#include <fishbone/window.h>
#include <fishbone/meshldr.h>
#include <fishbone/textureldr.h>
#include <fishbone/math.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);
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<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> normals);
struct Impl;
Impl* impl;
public:
Mesh(fishbone::Renderer* renderer, std::vector<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> normals, std::vector<int> elements);
public:
Mesh(fishbone::Renderer* renderer, std::vector<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> 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<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> normals) {
std::vector<struct fishbone::Vector3> v;
std::vector<struct fishbone::Vector2> t;
std::vector<struct fishbone::Vector3> n;
v = fishbone::quadToTriangle<struct fishbone::Vector3>(vertices);
t = fishbone::quadToTriangle<struct fishbone::Vector2>(texcoords);
n = fishbone::quadToTriangle<struct fishbone::Vector3>(normals);
this->triangle(v, t, n);
}
void triangle(std::vector<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> normals);
void quad(std::vector<struct fishbone::Vector2> vertices, std::vector<struct fishbone::Vector2> texcoords) {
std::vector<struct fishbone::Vector2> v;
std::vector<struct fishbone::Vector2> t;
v = fishbone::quadToTriangle<struct fishbone::Vector2>(vertices);
t = fishbone::quadToTriangle<struct fishbone::Vector2>(texcoords);
this->triangle(v, t);
}
void triangle(std::vector<struct fishbone::Vector2> vertices, std::vector<struct fishbone::Vector2> texcoords);
};
};
static float maxDistance = 64;
}; // namespace fishbone
#endif

View file

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

View file

@ -0,0 +1,16 @@
#ifndef __FISHBONE_FILESYSTEM_H__
#define __FISHBONE_FILESYSTEM_H__
#include <fishbone/pre.h>
namespace fishbone {
bool exists(std::string path);
};
/* no includes */
namespace fishbone {
bool exists(std::string path);
};
#endif

View file

@ -10,5 +10,11 @@
#include <fishbone/resource.h>
#include <fishbone/draw.h>
#include <fishbone/time.h>
#include <fishbone/base.h>
#include <fishbone/meshldr.h>
#include <fishbone/log.h>
#include <fishbone/math.h>
#include <fishbone/textureldr.h>
#include <fishbone/filesystem.h>
#endif

View file

@ -0,0 +1,35 @@
#ifndef __FISHBONE_LOG_H__
#define __FISHBONE_LOG_H__
#include <fishbone/pre.h>
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

View file

@ -1,23 +0,0 @@
#ifndef __FISHBONE_LOGGER_H__
#define __FISHBONE_LOGGER_H__
#include <fishbone/pre.h>
namespace fishbone {
class Logger {
public:
enum class Cause {
INFO,
DEBUG,
WARNING,
ERROR,
CRITICAL,
};
void log(std::string message);
void log(Cause cause, std::string message);
};
} // namespace fishbone
#endif

View file

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

View file

@ -0,0 +1,41 @@
#ifndef __FISHBONE_MATH_H__
#define __FISHBONE_MATH_H__
#include <fishbone/pre.h>
namespace fishbone {
float cot(float x);
template <typename T>
std::vector<T> quadToTriangle(std::vector<T> v);
}; // namespace fishbone
/* no includes */
namespace fishbone {
float cot(float x);
template <typename T>
std::vector<T> quadToTriangle(std::vector<T> v) {
std::vector<T> 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

View file

@ -0,0 +1,25 @@
#ifndef __FISHBONE_MESHLDR_H__
#define __FISHBONE_MESHLDR_H__
#include <fishbone/pre.h>
namespace fishbone {
class MeshData;
};
#include <fishbone/file.h>
namespace fishbone {
class MeshData {
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;
};
}; // namespace fishbone
#endif

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

@ -1,47 +1,21 @@
#ifndef __FISHBONE_RESOURCE_H__
#define __FISHBONE_RESOURCE_H__
#ifndef __FISHBONE_THREAD_H__
#define __FISHBONE_THREAD_H__
#include <fishbone/pre.h>
namespace fishbone {
class Resource;
class BaseEngine;
}; // namespace fishbone
#include <fishbone/file.h>
namespace fishbone {
class ResourceResolver {
public:
virtual bool exists(std::string path) = 0;
virtual size_t getSize(std::string path) = 0;
virtual bool copyData(std::string path, char* buffer, size_t maxSize) = 0;
};
class DirectoryResourceResolver : public ResourceResolver {
std::vector<std::string> searchPaths;
std::string findAbsolutePath(std::string path);
public:
DirectoryResourceResolver(std::vector<std::string> searchPaths);
bool exists(std::string path) override;
size_t getSize(std::string path) override;
bool copyData(std::string path, char* buffer, size_t maxSize) override;
};
class Resource {
char* buffer;
size_t bufferSize;
public:
fishbone::File* open(std::string path);
Resource(BaseEngine* engine, std::string path);
Resource(std::string path);
~Resource();
char* getBuffer();
size_t getSize();
fishbone::File* open(std::string path);
};
}; // namespace fishbone

View file

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

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

@ -7,7 +7,7 @@ namespace fishbone {
using AccurateClock = std::chrono::time_point<std::chrono::high_resolution_clock, std::chrono::high_resolution_clock::duration>;
fishbone::AccurateClock accurateTime();
};
}; // namespace fishbone
/* no includes */

View file

@ -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<std::string, std::vector<std::string>>;
}; // namespace fishbone
#endif

View file

@ -17,6 +17,10 @@ namespace fishbone {
~Window();
void poll();
void swapBuffer();
int width;
int height;
};
}; // namespace fishbone

52
engine/src/base.cc Normal file
View file

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

View file

@ -1,20 +1,48 @@
#include <fishbone/resource.h>
#include <fishbone/foundation.h>
fishbone::Client::Client(std::unordered_map<std::string, std::vector<std::string>> 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->resourceResolver = new fishbone::DirectoryResourceResolver({"/usr/share/fishbowl/assets"});
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;
}

View file

@ -1,12 +1,14 @@
#include <fishbone/config.h>
#ifdef FISHBONE_DRAW_USE_OPENGL
#include <fishbone/foundation.h>
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<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> normals, std::vector<int> 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<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 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<struct fishbone::Vector3> vertices, std::vector<struct fishbone::Vector2> texcoords, std::vector<struct fishbone::Vector3> 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<struct fishbone::Vector2> vertices, std::vector<struct fishbone::Vector2> 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

View file

@ -1,6 +0,0 @@
#include <fishbone/client.h>
#include <fishbone/resource.h>
fishbone::ResourceResolver* fishbone::BaseEngine::getResourceResolver() {
return this->resourceResolver;
}

View file

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

11
engine/src/filesystem.cc Normal file
View file

@ -0,0 +1,11 @@
#include <fishbone/foundation.h>
#include <sys/stat.h>
bool fishbone::exists(std::string path) {
struct stat s;
if(stat(path.c_str(), &s) == 0) return true;
return false;
}

25
engine/src/log.cc Normal file
View file

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

View file

@ -1,28 +0,0 @@
#include <cstdio>
#include <fishbone/logger.h>
static const char* CAUSE_NAMES[] = {
"INFO",
"DEBUG",
"WARNING",
"ERROR",
"CRITICAL",
};
static const char* CAUSE_COLORS[] = {
"", // INFO
"", // DEBUG
"\x1B[33m", // WARNING
"\x1B[31m", // ERROR
"\x1B[91m", // CRITICAL
};
static const char* FORMAT_CLEAR = "\x1B[0m";
void fishbone::Logger::log(Logger::Cause cause, std::string message) {
printf("%s[%s] %s%s\n", CAUSE_COLORS[(int)cause], CAUSE_NAMES[(int)cause], message.c_str(), FORMAT_CLEAR);
}
void fishbone::Logger::log(std::string message) {
log(Logger::Cause::INFO, message);
}

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);
}

128
engine/src/meshldr.cc Normal file
View file

@ -0,0 +1,128 @@
#include <fishbone/foundation.h>
static std::vector<int> parseFace(std::string s) {
std::vector<int> 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<struct fishbone::Vector3> v;
std::vector<struct fishbone::Vector2> vt;
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') {
if(l.size() == 0) {
} else if(l[0] == '#') {
} else {
std::vector<std::string> 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<int> 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;
}

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

1
engine/src/physics.cc Normal file
View file

@ -0,0 +1 @@
#include <fishbone/foundation.h>

View file

@ -1,35 +0,0 @@
#include <fishbone/client.h>
#include <fishbone/resource.h>
#include <vector>
fishbone::Resource::Resource(fishbone::BaseEngine* engine, std::string path) {
fishbone::ResourceResolver* resolver = engine->getResourceResolver();
if (!resolver->exists(path)) {
buffer = nullptr;
bufferSize = 0;
engine->log(Logger::Cause::WARNING, "Resource does not exist: " + path);
return;
}
this->bufferSize = resolver->getSize(path);
this->buffer = new char[bufferSize];
resolver->copyData(path, buffer, bufferSize);
}
fishbone::Resource::~Resource() {
if (this->buffer)
delete this->buffer;
}
char* fishbone::Resource::getBuffer() {
return this->buffer;
}
size_t fishbone::Resource::getSize() {
return this->bufferSize;
}
fishbone::DirectoryResourceResolver::DirectoryResourceResolver(std::vector<std::string> searchPaths) {
this->searchPaths = searchPaths;
}

View file

@ -1,46 +0,0 @@
#include <cstdio>
#include <fishbone/resource.h>
#include <unistd.h>
#include <sys/stat.h>
std::string fishbone::DirectoryResourceResolver::findAbsolutePath(std::string path) {
for(std::string searchPath : this->searchPaths) {
if(access((searchPath + "/" + path).c_str(), 0) == 0) {
return searchPath + "/" + path;
}
}
return "";
}
bool fishbone::DirectoryResourceResolver::exists(std::string path) {
return findAbsolutePath(path) != "";
}
size_t fishbone::DirectoryResourceResolver::getSize(std::string path) {
std::string absPath;
if ((absPath = findAbsolutePath(path)) == "")
return false;
struct stat buf;
stat(absPath.c_str(), &buf);
return buf.st_size;
}
bool fishbone::DirectoryResourceResolver::copyData(std::string path, char* buffer, size_t maxSize) {
std::string absPath;
if ((absPath = findAbsolutePath(path)) == "")
return false;
FILE* file = fopen(absPath.c_str(), "rb");
if (!file)
return false;
if (fread(buffer, maxSize, 1, file) == 0) {
fclose(file);
return false;
}
fclose(file);
return true;
}

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

View file

@ -1,5 +1,5 @@
#include <fishbone/foundation.h>
fishbone::AccurateClock fishbone::accurateTime(){
fishbone::AccurateClock fishbone::accurateTime() {
return std::chrono::high_resolution_clock::now();
}

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

@ -0,0 +1,64 @@
#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};
}
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};
}

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

View file

@ -6,6 +6,4 @@ file(GLOB_RECURSE SRCS src/**.cc src/**.c)
add_executable(fishbone_test ${SRCS})
target_link_libraries(fishbone_test PRIVATE fishbone Catch2::Catch2WithMain)
target_include_directories(fishbone_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
catch_discover_tests(fishbone_test)
file(COPY testresources DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
catch_discover_tests(fishbone_test)

View file

@ -1,34 +0,0 @@
#include "fishbone/client.h"
#include "fishbone/resource.h"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
#include <limits.h>
#include <unistd.h>
namespace {
class TestEngine : public fishbone::BaseEngine {
public:
TestEngine() {
// TODO: Use abstraction instead of relying on POSIX
char cwd[PATH_MAX];
getcwd(cwd, PATH_MAX);
this->resourceResolver = new fishbone::DirectoryResourceResolver({std::string(cwd) + "/testresources"});
}
};
} // namespace
static const char* LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi "
"ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum "
"dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia "
"deserunt mollit anim id est laborum.";
TEST_CASE("Directory loader") {
TestEngine engine;
fishbone::Resource rsc(&engine, "lorem.txt");
REQUIRE(rsc.getBuffer() != NULL);
REQUIRE(rsc.getSize() == strlen(LOREM));
REQUIRE(strncmp(rsc.getBuffer(), LOREM, rsc.getSize()) == 0);
}

View file

@ -1,5 +1,6 @@
#include "fishbone/thread.h"
#include <catch2/catch_test_macros.hpp>
#include <fishbone/thread.h>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>

View file

@ -1 +0,0 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.