# HG changeset patch # User John Tsiombikas # Date 1412298976 -10800 # Node ID 3f221bdc9bab5528bb7661b7ca6877801586c713 # Parent 0eca023ed9095f8d0728db919eb53a15fc0a81e7 mesh loading walk polys diff -r 0eca023ed909 -r 3f221bdc9bab src/game.cc --- a/src/game.cc Wed Oct 01 01:06:55 2014 +0300 +++ b/src/game.cc Fri Oct 03 04:16:16 2014 +0300 @@ -10,6 +10,7 @@ #include "console.h" #include "drawtext.h" #include "game_var.h" +#include "scenefile.h" static void draw_scene(); static void material(float r, float g, float b, float roughness); @@ -26,19 +27,33 @@ static unsigned int chess_tex; -static float cam_theta, cam_phi; -static Vector3 cam_pos; +static float cam_theta = -90, cam_phi; +static Vector3 cam_pos = {15.4, 0, 0}; static bool keystate[256]; static Console con; static dtx_font *con_font; -#define OPT_LOOK_WALK "look-walk" +static SceneFile scn; + +#define GVAR_LOOK_WALK "look-walk" +#define GVAR_MAX_STEP "max-step" bool game_init() { init_opengl(); + if(!(con_font = dtx_open_font_glyphmap("data/mono14.glyphmap"))) { + fprintf(stderr, "failed to open console font\n"); + return false; + } + con.set_font(con_font, 14); + con.set_size(7, 52); + con.set_position(0, 0, Console::CENTER); + con.set_command_func(con_handle); + con.set_echo(false); + + if(vr_init() == -1) { return false; } @@ -57,18 +72,14 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, chess_pixels); - if(!(con_font = dtx_open_font_glyphmap("data/mono14.glyphmap"))) { - fprintf(stderr, "failed to open console font\n"); + if(!scn.load("data/sibenik.goatsce")) { + fprintf(stderr, "failed to load scene file\n"); return false; } - con.set_font(con_font, 14); - con.set_size(7, 52); - con.set_position(0, 0, Console::CENTER); - con.set_command_func(con_handle); - con.set_echo(false); /* initialize all option variables */ - set_gvar_bool(OPT_LOOK_WALK, true); + set_gvar_bool(GVAR_LOOK_WALK, true); + set_gvar_num(GVAR_MAX_STEP, 0.5); return true; } @@ -105,7 +116,7 @@ dir += Vector3(0, 0, offs); } - if(get_gvar_bool(OPT_LOOK_WALK)) { + if(get_gvar_bool(GVAR_LOOK_WALK)) { float rot[4]; vr_view_rotation(0, rot); Quaternion q(rot[3], rot[0], rot[1], rot[2]); @@ -118,6 +129,8 @@ cam_pos.x += dir.x * cos_theta - dir.z * sin_theta; cam_pos.z += dir.x * sin_theta + dir.z * cos_theta; + float max_step = get_gvar_num(GVAR_MAX_STEP); + cam_pos = scn.find_walk_pos(cam_pos + Vector3(0, max_step, 0)); } void game_display() @@ -242,6 +255,8 @@ } } +MeshFace dbg_walk_face; + static void draw_scene() { float lpos[][4] = { @@ -261,6 +276,7 @@ glMatrixMode(GL_MODELVIEW); + /* glBindTexture(GL_TEXTURE_2D, chess_tex); glEnable(GL_TEXTURE_2D); material(1, 1, 1, 1); @@ -272,14 +288,33 @@ glTexCoord2f(0, 1); glVertex3f(-10, 0, -10); glEnd(); glDisable(GL_TEXTURE_2D); + */ - material(1, 1, 1, 0.4); + /*material(1, 1, 1, 0.4); glPushMatrix(); glTranslatef(0, 1.3, -10); glFrontFace(GL_CW); bezier_teapot(2.0); glFrontFace(GL_CCW); - glPopMatrix(); + glPopMatrix();*/ + + for(size_t i=0; idraw(); + } + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glBegin(GL_TRIANGLES); + glColor3f(0, 1, 0); + glVertex3fv(&dbg_walk_face.v[0].x); + glVertex3fv(&dbg_walk_face.v[1].x); + glVertex3fv(&dbg_walk_face.v[2].x); + glColor3f(1, 1, 1); + glEnd(); + + glPopAttrib(); } static void material(float r, float g, float b, float roughness) @@ -392,6 +427,11 @@ static void con_handle(const char *cmd) { + /* set debug values */ + set_gvar_num("cam-pos-x", cam_pos[0]); + set_gvar_num("cam-pos-y", cam_pos[1]); + set_gvar_num("cam-pos-z", cam_pos[2]); + std::vector argv; cmd = strip_spaces(cmd); diff -r 0eca023ed909 -r 3f221bdc9bab src/game_var.cc --- a/src/game_var.cc Wed Oct 01 01:06:55 2014 +0300 +++ b/src/game_var.cc Fri Oct 03 04:16:16 2014 +0300 @@ -1,3 +1,4 @@ +#include #include #include "game_var.h" @@ -138,4 +139,4 @@ res.push_back((it++)->first); } return res; -} \ No newline at end of file +} diff -r 0eca023ed909 -r 3f221bdc9bab src/material.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/material.cc Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,27 @@ +#include "material.h" +#include "opengl.h" + +Material::Material() + : diffuse(1, 1, 1) +{ + alpha = 1.0; + shininess = 60.0; + tex = 0; +} + +void Material::setup() const +{ + float diff[] = {diffuse.x, diffuse.y, diffuse.z, alpha}; + float spec[] = {specular.x, specular.y, specular.z, 1.0}; + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diff); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess > 128.0f ? 128.0f : shininess); + + if(tex) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex); + } else { + glDisable(GL_TEXTURE_2D); + } +} diff -r 0eca023ed909 -r 3f221bdc9bab src/material.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/material.h Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,19 @@ +#ifndef MATERIAL_H_ +#define MATERIAL_H_ + +#include + +class Material { +public: + Vector3 diffuse, specular; + float shininess; + float alpha; + + unsigned int tex; + + Material(); + + void setup() const; +}; + +#endif // MATERIAL_H_ diff -r 0eca023ed909 -r 3f221bdc9bab src/mesh.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mesh.cc Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,328 @@ +#include +#include "mesh.h" +#include "opengl.h" + +Mesh::Mesh() +{ + set_primitive(GL_TRIANGLES); + + for(int i=0; iprim = GL_TRIANGLES; + } else { + this->prim = prim; + } + + switch(this->prim) { + case GL_TRIANGLES: + prim_verts = 3; + break; + + case GL_QUADS: + prim_verts = 4; + break; + + case GL_LINES: + prim_verts = 2; + break; + + case GL_POINTS: + prim_verts = 1; + break; + + default: + break; + } +} + +void Mesh::set_attrib_location(int attr, int loc) +{ + attrib[attr].sdrloc = loc; +} + +float *Mesh::set_vertex_data(int attr, int nelem, int count, float *data) +{ + attrib[attr].data.resize(count * nelem); + if(data) { + memcpy(&attrib[attr].data[0], data, nelem * count * sizeof(float)); + } + + attrib[attr].nelems = nelem; + attrib[attr].vbo_valid = false; + + num_verts = count; + + return &attrib[attr].data[0]; +} + +unsigned int *Mesh::set_index_data(int count, unsigned int *data) +{ + index.resize(count); + if(data) { + memcpy(&index[0], data, count * sizeof(unsigned int)); + } + + num_idx = count; + ibo_valid = false; + + return &index[0]; +} + +int Mesh::get_vertex_count() const +{ + return num_verts; +} + +float *Mesh::get_vertex_data(int attr) +{ + if(attrib[attr].data.empty()) { + return 0; + } + return &attrib[attr].data[0]; +} + +const float *Mesh::get_vertex_data(int attr) const +{ + if(attrib[attr].data.empty()) { + return 0; + } + return &attrib[attr].data[0]; +} + +int Mesh::get_index_count() const +{ + return num_idx; +} + +unsigned int *Mesh::get_index_data() +{ + if(index.empty()) { + return 0; + } + return &index[0]; +} + +const unsigned int *Mesh::get_index_data() const +{ + if(index.empty()) { + return 0; + } + return &index[0]; +} + +int Mesh::get_face_count() const +{ + if(index.empty()) { + return get_vertex_count() / prim_verts; + } + return get_index_count() / prim_verts; +} + +MeshFace Mesh::get_face(int idx) const +{ + MeshFace face; + face.vcount = prim_verts; + + int nfaces = get_face_count(); + if(idx < 0 || idx >= nfaces) { + return face; + } + + const Vector3 *verts = (const Vector3*)&attrib[MESH_VERTEX].data[0]; + + if(index.empty()) { + for(int i=0; i<3; i++) { + face.v[i] = verts[idx * 3 + i]; + } + + } else { + for(int i=0; i<3; i++) { + int vidx = index[idx * 3 + i]; + face.v[i] = verts[vidx]; + } + } + + return face; +} + + +void Mesh::begin(int prim) +{ + if(prim == -1) { + this->prim = GL_TRIANGLES; + } else { + this->prim = prim; + } + + clear(); + + cur_norm_valid = false; + cur_tc_valid = false; + cur_tang_valid = false; +} + +void Mesh::end() +{ +} + +void Mesh::vertex(float x, float y, float z) +{ + if(cur_norm_valid) { + attrib[MESH_NORMAL].data.push_back(cur_norm.x); + attrib[MESH_NORMAL].data.push_back(cur_norm.y); + attrib[MESH_NORMAL].data.push_back(cur_norm.z); + } + if(cur_tc_valid) { + attrib[MESH_TEXCOORD].data.push_back(cur_tc.x); + attrib[MESH_TEXCOORD].data.push_back(cur_tc.y); + } + if(cur_tang_valid) { + attrib[MESH_TANGENT].data.push_back(cur_tang.x); + attrib[MESH_TANGENT].data.push_back(cur_tang.y); + attrib[MESH_TANGENT].data.push_back(cur_tang.z); + } + attrib[MESH_VERTEX].data.push_back(x); + attrib[MESH_VERTEX].data.push_back(y); + attrib[MESH_VERTEX].data.push_back(z); +} + +void Mesh::normal(float x, float y, float z) +{ + cur_norm = Vector3(x, y, z); + cur_norm_valid = true; +} + +void Mesh::texcoord(float x, float y) +{ + cur_tc = Vector2(x, y); + cur_tc_valid = true; +} + +void Mesh::tangent(float x, float y, float z) +{ + cur_tang = Vector3(x, y, z); + cur_tang_valid = true; +} + +void Mesh::draw() const +{ + if(attrib[MESH_VERTEX].data.empty()) { + return; + } + + bool use_norm = !attrib[MESH_NORMAL].data.empty(); + bool use_tc = !attrib[MESH_TEXCOORD].data.empty(); + bool use_tang = !attrib[MESH_TANGENT].data.empty(); + int norm_loc, tc_loc, tang_loc; + + const float *ptr = &attrib[MESH_VERTEX].data[0]; + int loc = attrib[MESH_VERTEX].sdrloc; + if(loc == -1) { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, ptr); + } else { + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0, ptr); + } + + if(use_norm) { + const float *ptr = &attrib[MESH_NORMAL].data[0]; + norm_loc = attrib[MESH_NORMAL].sdrloc; + if(norm_loc == -1) { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, ptr); + } else { + glEnableVertexAttribArray(norm_loc); + glVertexAttribPointer(norm_loc, attrib[MESH_NORMAL].nelems, GL_FLOAT, 0, 0, ptr); + } + } + + if(use_tc) { + const float *ptr = &attrib[MESH_TEXCOORD].data[0]; + tc_loc = attrib[MESH_TEXCOORD].sdrloc; + if(tc_loc == -1) { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, ptr); + } else { + glEnableVertexAttribArray(tc_loc); + glVertexAttribPointer(tc_loc, attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0, ptr); + } + } + + if(!attrib[MESH_TANGENT].data.empty()) { + const float *ptr = &attrib[MESH_TANGENT].data[0]; + tang_loc = attrib[MESH_TANGENT].sdrloc; + if(tang_loc != -1) { + glEnableVertexAttribArray(tang_loc); + glVertexAttribPointer(tang_loc, attrib[MESH_TANGENT].nelems, GL_FLOAT, 0, 0, ptr); + } + } + + if(!index.empty()) { + glDrawElements(prim, num_idx, GL_UNSIGNED_INT, &index[0]); + } else { + glDrawArrays(prim, 0, num_verts * 3); + } + + if(use_norm) { + if(norm_loc == -1) { + glDisableClientState(GL_NORMAL_ARRAY); + } else { + glDisableVertexAttribArray(norm_loc); + } + } + if(use_tc) { + if(tc_loc == -1) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } else { + glDisableVertexAttribArray(tc_loc); + } + } + if(use_tang) { + if(tang_loc != -1) { + glDisableVertexAttribArray(tang_loc); + } + } +} diff -r 0eca023ed909 -r 3f221bdc9bab src/mesh.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mesh.h Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,83 @@ +#ifndef MESH_H_ +#define MESH_H_ + +#include +#include + +enum MeshAttrib { + MESH_VERTEX, + MESH_NORMAL, + MESH_TEXCOORD, + MESH_TANGENT, + + NUM_MESH_ATTRIBS +}; + +struct MeshAttribData { + std::vector data; + int nelems; + int sdrloc; + + int vbo_size; + unsigned int vbo; + bool vbo_valid; +}; + +struct MeshFace { + int vcount; + Vector3 v[4]; +}; + +class Mesh { +private: + int prim, prim_verts; + MeshAttribData attrib[NUM_MESH_ATTRIBS]; + int num_verts; + + std::vector index; + int num_idx; + unsigned int ibo; + int ibo_size; + bool ibo_valid; + + unsigned int vbo_usage, ibo_usage; + + Vector3 cur_norm, cur_tang; + Vector2 cur_tc; + bool cur_norm_valid, cur_tc_valid, cur_tang_valid; + +public: + Mesh(); + ~Mesh(); + + void clear(); + + void set_primitive(int prim = -1); + void set_attrib_location(int attr, int loc); + + float *set_vertex_data(int attr, int nelem, int count, float *data = 0); + unsigned int *set_index_data(int count, unsigned int *data = 0); + + int get_vertex_count() const; + float *get_vertex_data(int attr); + const float *get_vertex_data(int attr) const; + + int get_index_count() const; + unsigned int *get_index_data(); + const unsigned int *get_index_data() const; + + int get_face_count() const; + MeshFace get_face(int idx) const; + + void begin(int prim = -1); + void end(); + + void vertex(float x, float y, float z); + void normal(float x, float y, float z); + void texcoord(float x, float y); + void tangent(float x, float y, float z); + + void draw() const; +}; + +#endif // MESH_H_ diff -r 0eca023ed909 -r 3f221bdc9bab src/object.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/object.cc Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,26 @@ +#include "object.h" +#include "opengl.h" + +Object::Object() +{ + mesh = 0; +} + +void Object::set_mesh(Mesh *m) +{ + mesh = m; +} + +void Object::draw() const +{ + if(!mesh) return; + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMultTransposeMatrixf(xform[0]); + + mtl.setup(); + mesh->draw(); + + glPopMatrix(); +} diff -r 0eca023ed909 -r 3f221bdc9bab src/object.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/object.h Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,23 @@ +#ifndef OBJECT_H_ +#define OBJECT_H_ + +#include +#include "mesh.h" +#include "material.h" + +class Object { +private: + Mesh *mesh; + +public: + Material mtl; + Matrix4x4 xform; + + Object(); + + void set_mesh(Mesh *m); + + void draw() const; +}; + +#endif /* OBJECT_H_ */ diff -r 0eca023ed909 -r 3f221bdc9bab src/scenefile.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scenefile.cc Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include "scenefile.h" +#include "goat3d.h" +#include "texman.h" + +SceneFile::SceneFile() +{ +} + +SceneFile::~SceneFile() +{ +} + +bool SceneFile::load(const char *fname) +{ + std::map meshmap; + + struct goat3d *g3d = goat3d_create(); + if(!g3d) return false; + + if(goat3d_load(g3d, fname) == -1) { + return false; + } + + int nmeshes = goat3d_get_mesh_count(g3d); + for(int i=0; iset_vertex_data(MESH_VERTEX, 3, nverts, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_VERTEX)); + + int nnorm = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_NORMAL); + if(nnorm) { + assert(nnorm == nverts); + m->set_vertex_data(MESH_NORMAL, 3, nnorm, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_NORMAL)); + } + + int ntex = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_TEXCOORD); + if(ntex) { + assert(ntex == nverts); + m->set_vertex_data(MESH_TEXCOORD, 2, ntex, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_TEXCOORD)); + } + + int ntang = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_TANGENT); + if(ntang) { + assert(ntang == nverts); + m->set_vertex_data(MESH_TANGENT, 3, ntang, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_TANGENT)); + } + + int nfaces = goat3d_get_mesh_face_count(gm); + if(nfaces) { + m->set_index_data(nfaces * 3, (unsigned int*)goat3d_get_mesh_faces(gm)); + } + + mesh.push_back(m); + meshmap[gm] = m; + // TODO: do this after nodes are loaded per object to pre-transform if applicable + colmesh.push_back(m); + } + + /* iterate the nodes and create objects */ + int nnodes = goat3d_get_node_count(g3d); + for(int i=0; iset_mesh(m); + + float mat[16]; + goat3d_get_node_matrix(gn, mat, 0); + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + obj->xform[i][j] = mat[i * 4 + j]; + } + } + + struct goat3d_material *gmtl = goat3d_get_mesh_mtl(gm); + const float *col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_DIFFUSE); + if(col) { + obj->mtl.diffuse = Vector3(col[0], col[1], col[2]); + } + if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_SPECULAR))) { + obj->mtl.specular = Vector3(col[0], col[1], col[2]); + } + if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_ALPHA))) { + obj->mtl.alpha = col[0]; + } + if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_SHININESS))) { + obj->mtl.shininess = col[0]; + } + const char *fname = goat3d_get_mtl_attrib_map(gmtl, GOAT3D_MAT_ATTR_DIFFUSE); + if(fname) { + obj->mtl.tex = get_texture(fname); + } + + this->obj.push_back(obj); + } + + goat3d_free(g3d); + return true; +} + +static Vector3 bary(const Vector3 &a, const Vector3 &b, const Vector3 &c, + const Vector3 &p) +{ + float ctri = cross_product(b - a, c - a).length(); + if(ctri == 0.0f) { + return Vector3(2, 0, 0); + } + + float ca = cross_product(b - p, c - p).length() / ctri; + float cb = cross_product(a - p, c - p).length() / ctri; + float cc = cross_product(a - p, b - p).length() / ctri; + + return Vector3(ca, cb, cc); +} + +extern MeshFace dbg_walk_face; + +Vector3 SceneFile::find_walk_pos(const Vector3 &pos) const +{ + float max_y = -FLT_MAX; + Vector3 pos_xz = Vector3(pos.x, 0, pos.z); + + for(size_t i=0; iget_face_count(); + for(int j=0; jget_face(j); + + Vector3 v0_xz = Vector3(face.v[0].x, 0, face.v[0].z); + Vector3 v1_xz = Vector3(face.v[1].x, 0, face.v[1].z); + Vector3 v2_xz = Vector3(face.v[2].x, 0, face.v[2].z); + + Vector3 bc = bary(v0_xz, v1_xz, v2_xz, pos_xz); + float bsum = bc.x + bc.y + bc.z; + if(bsum > 1.000001) { + continue; + } + + float y = face.v[0].y * bc.x + face.v[1].y * bc.y + face.v[2].y * bc.z; + if(y > max_y && y <= pos.y) { + dbg_walk_face = face; + max_y = y; + } + } + } + + if(max_y == -FLT_MAX) { + return pos; + } + return Vector3(pos.x, max_y, pos.z); +} diff -r 0eca023ed909 -r 3f221bdc9bab src/scenefile.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scenefile.h Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,22 @@ +#ifndef SCENEFILE_H_ +#define SCENEFILE_H_ + +#include +#include "mesh.h" +#include "object.h" + +class SceneFile { +public: + std::vector mesh; + std::vector colmesh; + std::vector obj; + + SceneFile(); + ~SceneFile(); + + bool load(const char *fname); + + Vector3 find_walk_pos(const Vector3 &pos) const; +}; + +#endif // SCENEFILE_H_ diff -r 0eca023ed909 -r 3f221bdc9bab src/texman.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/texman.cc Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include "opengl.h" +#include "texman.h" + +static std::string find_datafile(const std::string &fname); + +static std::map textures; +static const char *paths[] = { + "data", + 0 +}; + +unsigned int get_texture(const char *fname) +{ + unsigned int tex; + + if(!fname || !*fname) { + return 0; + } + + std::map::const_iterator it = textures.find(fname); + if(it != textures.end()) { + tex = it->second; + } else { + if(!(tex = img_gltexture_load(find_datafile(fname).c_str()))) { + fprintf(stderr, "failed to load image: %s\n", fname); + } else { + textures[fname] = tex; + } + } + + return tex; +} + +static std::string find_datafile(const std::string &fname) +{ + FILE *fp; + + for(int i=0; paths[i]; i++) { + std::string path = paths[i] + std::string("/") + fname; + if((fp = fopen(path.c_str(), "rb"))) { + fclose(fp); + return path; + } + } + + return fname; +} diff -r 0eca023ed909 -r 3f221bdc9bab src/texman.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/texman.h Fri Oct 03 04:16:16 2014 +0300 @@ -0,0 +1,6 @@ +#ifndef TEXMAN_H_ +#define TEXMAN_H_ + +unsigned int get_texture(const char *fname); + +#endif