eqemu
changeset 3:f9274bebe55e
adding 3d graphics stuff
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 17 Jul 2014 02:35:19 +0300 |
parents | 48dce4ee4850 |
children | 3d3656360a82 |
files | src/material.cc src/material.h src/mesh.cc src/mesh.h src/object.cc src/object.h src/objfile.cc src/scene.cc src/scene.h src/vmath.h |
diffstat | 10 files changed, 899 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/material.cc Thu Jul 17 02:35:19 2014 +0300 1.3 @@ -0,0 +1,20 @@ 1.4 +#include <GL/glew.h> 1.5 +#include "material.h" 1.6 + 1.7 +Material::Material() 1.8 + : color(1, 1, 1), specular(0, 0, 0) 1.9 +{ 1.10 + shininess = 1.0; 1.11 + alpha = 1.0; 1.12 +} 1.13 + 1.14 +void Material::setup() const 1.15 +{ 1.16 + float col[] = {color.x, color.y, color.z, alpha}; 1.17 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); 1.18 + 1.19 + float spec[] = {specular.x, specular.y, specular.z, 1.0}; 1.20 + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); 1.21 + 1.22 + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess > 128 ? 128 : shininess); 1.23 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/material.h Thu Jul 17 02:35:19 2014 +0300 2.3 @@ -0,0 +1,19 @@ 2.4 +#ifndef MATERIAL_H_ 2.5 +#define MATERIAL_H_ 2.6 + 2.7 +#include "vmath.h" 2.8 + 2.9 +class Material { 2.10 +public: 2.11 + Vector3 ambient; 2.12 + Vector3 diffuse; 2.13 + Vector3 specular; 2.14 + float shininess; 2.15 + float alpha; 2.16 + 2.17 + Material(); 2.18 + 2.19 + void setup() const; 2.20 +}; 2.21 + 2.22 +#endif // MATERIAL_H_
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/mesh.cc Thu Jul 17 02:35:19 2014 +0300 3.3 @@ -0,0 +1,101 @@ 3.4 +#include <stdio.h> 3.5 +#include <string.h> 3.6 +#include <GL/glew.h> 3.7 +#include "mesh.h" 3.8 + 3.9 +#define ALL_VALID 0xffffffff 3.10 + 3.11 +Mesh::Mesh() 3.12 +{ 3.13 + buf_valid = ALL_VALID; 3.14 + 3.15 + for(int i=0; i<vcount; i++) { 3.16 + attr[i] = 0; 3.17 + attr_size[i] = 0; 3.18 + buf_valid &= ~(1 << i); 3.19 + } 3.20 + vcount = 0; 3.21 + glGenBuffers(NUM_MESH_ATTRIBS, vbo); 3.22 +} 3.23 + 3.24 +Mesh::~Mesh() 3.25 +{ 3.26 + for(int i=0; i<vcount; i++) { 3.27 + delete [] attr[i]; 3.28 + } 3.29 + glDeleteBuffers(NUM_MESH_ATTRIBS, vbo); 3.30 +} 3.31 + 3.32 +float *Mesh::set_attrib(int aidx, int count, int elemsz, float *data) 3.33 +{ 3.34 + if(attr[aidx]) { 3.35 + delete [] attr[aidx]; 3.36 + } 3.37 + attr[aidx] = new float[count * elemsz]; 3.38 + attr_size[aidx] = elemsz; 3.39 + buf_valid &= ~(1 << aidx); 3.40 + return attr[aidx]; 3.41 +} 3.42 + 3.43 +float *Mesh::get_attrib(int aidx) 3.44 +{ 3.45 + buf_valid &= ~(1 << aidx); 3.46 + return attr[aidx]; 3.47 +} 3.48 + 3.49 +const float *Mesh::get_attrib(int aidx) const 3.50 +{ 3.51 + return attr[aidx]; 3.52 +} 3.53 + 3.54 +void Mesh::draw() const 3.55 +{ 3.56 + update_buffers(); 3.57 + 3.58 + if(!vbo[MESH_ATTR_VERTEX]) { 3.59 + fprintf(stderr, "trying to render without a vertex buffer\n"); 3.60 + return; 3.61 + } 3.62 + 3.63 + glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]); 3.64 + glEnableClientState(GL_VERTEX_ARRAY); 3.65 + glVertexPointer(attr_size[MESH_ATTR_VERTEX], GL_FLOAT, 0, 0); 3.66 + 3.67 + if(vbo[MESH_ATTR_NORMAL]) { 3.68 + glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]); 3.69 + glEnableClientState(GL_NORMAL_ARRAY); 3.70 + glNormalPointer(GL_FLOAT, 0, 0); 3.71 + } 3.72 + if(vbo[MESH_ATTR_TEXCOORD]) { 3.73 + glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]); 3.74 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 3.75 + glTexCoordPointer(attr_size[MESH_ATTR_TEXCOORD], GL_FLOAT, 0, 0); 3.76 + } 3.77 + glBindBuffer(GL_ARRAY_BUFFER, 0); 3.78 + 3.79 + glDrawArrays(GL_TRIANGLES, 0, vcount); 3.80 + 3.81 + glDisableClientState(GL_VERTEX_ARRAY); 3.82 + if(vbo[MESH_ATTR_NORMAL]) { 3.83 + glDisableClientState(GL_NORMAL_ARRAY); 3.84 + } 3.85 + if(vbo[MESH_ATTR_TEXCOORD]) { 3.86 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 3.87 + } 3.88 +} 3.89 + 3.90 +void Mesh::update_buffers() const 3.91 +{ 3.92 + if(buf_valid == ALL_VALID) { 3.93 + return; 3.94 + } 3.95 + 3.96 + for(int i=0; i<NUM_MESH_ATTRIBS; i++) { 3.97 + if((buf_valid & (1 << i)) == 0) { 3.98 + glBindBuffer(GL_ARRAY_BUFFER, vbo[i]); 3.99 + glBufferData(GL_ARRAY_BUFFER, vcount * attr_size[i] * sizeof(float), 3.100 + attr[i], GL_STATIC_DRAW); 3.101 + buf_valid |= 1 << i; 3.102 + } 3.103 + } 3.104 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/mesh.h Thu Jul 17 02:35:19 2014 +0300 4.3 @@ -0,0 +1,33 @@ 4.4 +#ifndef MESH_H_ 4.5 +#define MESH_H_ 4.6 + 4.7 +enum { 4.8 + MESH_ATTR_VERTEX, 4.9 + MESH_ATTR_NORMAL, 4.10 + MESH_ATTR_TEXCOORD, 4.11 + 4.12 + NUM_MESH_ATTRIBS 4.13 +}; 4.14 + 4.15 +class Mesh { 4.16 +private: 4.17 + float *attr[NUM_MESH_ATTRIBS]; 4.18 + int vcount; 4.19 + unsigned int vbo[NUM_MESH_ATTRIBS]; 4.20 + int attr_size[NUM_MESH_ATTRIBS]; 4.21 + 4.22 + mutable unsigned int buf_valid; /* bitmask */ 4.23 + void update_buffers() const; 4.24 + 4.25 +public: 4.26 + Mesh(); 4.27 + ~Mesh(); 4.28 + 4.29 + float *set_attrib(int aidx, int count, int elemsz, float *data = 0); 4.30 + float *get_attrib(int aidx); 4.31 + const float *get_attrib(int aidx) const; 4.32 + 4.33 + void draw() const; 4.34 +}; 4.35 + 4.36 +#endif // MESH_H_
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/object.cc Thu Jul 17 02:35:19 2014 +0300 5.3 @@ -0,0 +1,24 @@ 5.4 +#include "object.h" 5.5 + 5.6 +Object::Object() 5.7 +{ 5.8 + mesh = 0; 5.9 +} 5.10 + 5.11 +void Object::set_mesh(Mesh *mesh) 5.12 +{ 5.13 + this->mesh = mesh; 5.14 +} 5.15 + 5.16 +Mesh *Object::get_mesh() const 5.17 +{ 5.18 + return mesh; 5.19 +} 5.20 + 5.21 +void Object::render() const 5.22 +{ 5.23 + if(!mesh) return; 5.24 + 5.25 + mtl.setup(); 5.26 + mesh->draw(); 5.27 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/object.h Thu Jul 17 02:35:19 2014 +0300 6.3 @@ -0,0 +1,22 @@ 6.4 +#ifndef OBJECT_H_ 6.5 +#define OBJECT_H_ 6.6 + 6.7 +#include "mesh.h" 6.8 +#include "material.h" 6.9 + 6.10 +class Object { 6.11 +private: 6.12 + Mesh *mesh; 6.13 + 6.14 +public: 6.15 + Material mtl; 6.16 + 6.17 + Object(); 6.18 + 6.19 + void set_mesh(Mesh *mesh); 6.20 + Mesh *get_mesh() const; 6.21 + 6.22 + void render() const; 6.23 +}; 6.24 + 6.25 +#endif // OBJECT_H_
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/objfile.cc Thu Jul 17 02:35:19 2014 +0300 7.3 @@ -0,0 +1,542 @@ 7.4 +#include <stdlib.h> 7.5 +#include <string.h> 7.6 +#include <ctype.h> 7.7 +#include <limits.h> 7.8 +#include <vector> 7.9 +#include <map> 7.10 +#include <string> 7.11 +#include <sstream> 7.12 +#include <iomanip> 7.13 +#include "scene.h" 7.14 + 7.15 +using namespace std; 7.16 + 7.17 +#define COMMANDS \ 7.18 + CMD(V), \ 7.19 + CMD(VN), \ 7.20 + CMD(VT), \ 7.21 + CMD(F), \ 7.22 + CMD(O), \ 7.23 + CMD(G), \ 7.24 + CMD(MTLLIB), \ 7.25 + CMD(USEMTL), \ 7.26 + CMD(NEWMTL), \ 7.27 + CMD(KA), \ 7.28 + CMD(KD), \ 7.29 + CMD(KS), \ 7.30 + CMD(NS), \ 7.31 + CMD(NI), \ 7.32 + CMD(D), \ 7.33 + CMD(TR), \ 7.34 + CMD(MAP_KD), \ 7.35 + CMD(MAP_KS), \ 7.36 + CMD(MAP_NS), \ 7.37 + CMD(MAP_D), \ 7.38 + CMD(REFL), \ 7.39 + CMD(BUMP) 7.40 + 7.41 +#define CMD(x) CMD_##x 7.42 +enum { 7.43 + COMMANDS, 7.44 + CMD_UNK 7.45 +}; 7.46 +#undef CMD 7.47 + 7.48 +#define CMD(x) #x 7.49 +static const char *cmd_names[] = { 7.50 + COMMANDS, 7.51 + 0 7.52 +}; 7.53 +#undef CMD 7.54 + 7.55 + 7.56 +struct ObjFace { 7.57 + int elem; 7.58 + int v[4], n[4], t[4]; 7.59 +}; 7.60 + 7.61 +struct ObjFile { 7.62 + string cur_obj, cur_mat; 7.63 + vector<Vector3> v, vn; 7.64 + vector<Vector2> vt; 7.65 + vector<ObjFace> f; 7.66 +}; 7.67 + 7.68 +typedef Vector3 Color; 7.69 + 7.70 +struct ObjMat { 7.71 + string name; // newmtl <name> 7.72 + Color ambient, diffuse, specular; // Ka, Kd, Ks 7.73 + float shininess; // Ns 7.74 + float ior; // Ni 7.75 + float alpha; // d, Tr 7.76 + 7.77 + string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d 7.78 + string tex_refl; // refl -type sphere|cube file 7.79 + string tex_bump; // bump 7.80 + 7.81 + ObjMat() { reset(); } 7.82 + 7.83 + void reset() { 7.84 + ambient = diffuse = Color(0.5, 0.5, 0.5); 7.85 + specular = Color(0.0, 0.0, 0.0); 7.86 + name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; 7.87 + shininess = 0; 7.88 + ior = alpha = 1; 7.89 + } 7.90 +}; 7.91 + 7.92 +static bool read_materials(FILE *fp, vector<ObjMat> *vmtl); 7.93 +static Object *cons_object(ObjFile *obj); 7.94 + 7.95 +static int get_cmd(char *str); 7.96 +static bool is_int(const char *str); 7.97 +static bool is_float(const char *str); 7.98 +static bool parse_vec(Vector3 *vec); 7.99 +static bool parse_color(Color *col); 7.100 +static bool parse_face(ObjFace *face); 7.101 +static const char *parse_map(); 7.102 + 7.103 + 7.104 +static map<string, Material> matlib; 7.105 + 7.106 + 7.107 +#define INVALID_IDX INT_MIN 7.108 + 7.109 +#define SEP " \t\n\r\v" 7.110 +#define BUF_SZ 512 7.111 +bool Scene::load_obj(FILE *fp) 7.112 +{ 7.113 + static int seq; 7.114 + char cur_name[16]; 7.115 + stringstream sstr; 7.116 + 7.117 + ObjFile obj; 7.118 + 7.119 + sprintf(cur_name, "default%02d.obj", seq++); 7.120 + obj.cur_obj = cur_name; 7.121 + 7.122 + int prev_cmd = 0, obj_added = 0; 7.123 + for(;;) { 7.124 + Vector3 vec; 7.125 + ObjFace face; 7.126 + 7.127 + char line[BUF_SZ]; 7.128 + fgets(line, sizeof line, fp); 7.129 + if(feof(fp)) { 7.130 + break; 7.131 + } 7.132 + 7.133 + char *tok; 7.134 + if(!(tok = strtok(line, SEP))) { 7.135 + continue; // ignore empty lines 7.136 + } 7.137 + 7.138 + int cmd; 7.139 + if((cmd = get_cmd(tok)) == -1) { 7.140 + continue; // ignore unknown commands ... 7.141 + } 7.142 + 7.143 + switch(cmd) { 7.144 + case CMD_V: 7.145 + if(!parse_vec(&vec)) { 7.146 + continue; 7.147 + } 7.148 + obj.v.push_back(vec); 7.149 + break; 7.150 + 7.151 + case CMD_VN: 7.152 + if(!parse_vec(&vec)) { 7.153 + continue; 7.154 + } 7.155 + obj.vn.push_back(vec); 7.156 + break; 7.157 + 7.158 + case CMD_VT: 7.159 + if(!parse_vec(&vec)) { 7.160 + continue; 7.161 + } 7.162 + vec.y = 1.0 - vec.y; 7.163 + obj.vt.push_back(Vector2(vec.x, vec.y)); 7.164 + break; 7.165 + 7.166 + case CMD_O: 7.167 + case CMD_G: 7.168 + if(prev_cmd == CMD_O || prev_cmd == CMD_G) { 7.169 + break; // just in case we've got both of them in a row 7.170 + } 7.171 + /* if we have any previous data, group them up, add the object 7.172 + * and continue with the new one... 7.173 + */ 7.174 + if(!obj.f.empty()) { 7.175 + Object *robj = cons_object(&obj); 7.176 + robj->mtl = matlib[obj.cur_mat]; 7.177 + add_object(robj); 7.178 + obj_added++; 7.179 + 7.180 + obj.f.clear(); // clean the face list 7.181 + } 7.182 + if((tok = strtok(0, SEP))) { 7.183 + obj.cur_obj = tok; 7.184 + } else { 7.185 + sprintf(cur_name, "default%02d.obj", seq++); 7.186 + obj.cur_obj = cur_name; 7.187 + } 7.188 + break; 7.189 + 7.190 + case CMD_MTLLIB: 7.191 + if((tok = strtok(0, SEP))) { 7.192 + FILE *mfile; 7.193 + if(!(mfile = fopen(tok, "rb"))) { 7.194 + fprintf(stderr, "failed to open material library: %s\n", tok); 7.195 + continue; 7.196 + } 7.197 + 7.198 + // load all materials of the mtl file into a vector 7.199 + vector<ObjMat> vmtl; 7.200 + if(!read_materials(mfile, &vmtl)) { 7.201 + continue; 7.202 + } 7.203 + fclose(mfile); 7.204 + 7.205 + // and add them all to the scene 7.206 + for(size_t i=0; i<vmtl.size(); i++) { 7.207 + Material mat; 7.208 + mat.ambient = vmtl[i].ambient; 7.209 + mat.diffuse = vmtl[i].diffuse; 7.210 + mat.specular = vmtl[i].specular; 7.211 + mat.shininess = vmtl[i].shininess; 7.212 + mat.alpha = vmtl[i].alpha; 7.213 + 7.214 + /*if(vmtl[i].tex_dif.length()) { 7.215 + mat.set_texture(get_texture(vmtl[i].tex_dif.c_str())); 7.216 + }*/ 7.217 + 7.218 + matlib[vmtl[i].name] = mat; 7.219 + } 7.220 + } 7.221 + break; 7.222 + 7.223 + case CMD_USEMTL: 7.224 + if((tok = strtok(0, SEP))) { 7.225 + obj.cur_mat = tok; 7.226 + } else { 7.227 + obj.cur_mat = ""; 7.228 + } 7.229 + break; 7.230 + 7.231 + case CMD_F: 7.232 + if(!parse_face(&face)) { 7.233 + continue; 7.234 + } 7.235 + 7.236 + // convert negative indices to regular indices 7.237 + for(int i=0; i<4; i++) { 7.238 + if(face.v[i] < 0 && face.v[i] != INVALID_IDX) { 7.239 + face.v[i] = obj.v.size() + face.v[i]; 7.240 + } 7.241 + if(face.n[i] < 0 && face.n[i] != INVALID_IDX) { 7.242 + face.n[i] = obj.vn.size() + face.n[i]; 7.243 + } 7.244 + if(face.t[i] < 0 && face.t[i] != INVALID_IDX) { 7.245 + face.t[i] = obj.vt.size() + face.t[i]; 7.246 + } 7.247 + } 7.248 + 7.249 + // break quads into triangles if needed 7.250 + obj.f.push_back(face); 7.251 + if(face.elem == 4) { 7.252 + face.v[1] = face.v[2]; 7.253 + face.n[1] = face.n[2]; 7.254 + face.t[1] = face.t[2]; 7.255 + 7.256 + face.v[2] = face.v[3]; 7.257 + face.n[2] = face.n[3]; 7.258 + face.t[2] = face.t[3]; 7.259 + 7.260 + obj.f.push_back(face); 7.261 + } 7.262 + break; 7.263 + 7.264 + default: 7.265 + break; // ignore unknown commands 7.266 + } 7.267 + 7.268 + prev_cmd = cmd; 7.269 + } 7.270 + 7.271 + // reached end of file... 7.272 + if(!obj.f.empty()) { 7.273 + Object *robj = cons_object(&obj); 7.274 + robj->mtl = matlib[obj.cur_mat]; 7.275 + add_object(robj); 7.276 + obj_added++; 7.277 + } 7.278 + 7.279 + return obj_added > 0; 7.280 +} 7.281 + 7.282 +static Object *cons_object(ObjFile *obj) 7.283 +{ 7.284 + Object *robj; 7.285 + Vector3 *varr, *narr; 7.286 + Vector2 *tarr; 7.287 + 7.288 + int nelem = obj->f.size() * 3; 7.289 + 7.290 + try { 7.291 + robj = new Object; 7.292 + varr = new Vector3[nelem]; 7.293 + narr = new Vector3[nelem]; 7.294 + tarr = new Vector2[nelem]; 7.295 + } 7.296 + catch(...) { 7.297 + return 0; 7.298 + } 7.299 + /*if(obj->cur_obj.length() > 0) { 7.300 + robj->set_name(obj->cur_obj.c_str()); 7.301 + }*/ 7.302 + 7.303 + // need at least one of each element 7.304 + bool added_norm = false, added_tc = false; 7.305 + if(obj->vn.empty()) { 7.306 + obj->vn.push_back(Vector3(0, 0, 0)); 7.307 + added_norm = true;; 7.308 + } 7.309 + if(obj->vt.empty()) { 7.310 + obj->vt.push_back(Vector2(0, 0)); 7.311 + added_tc = true; 7.312 + } 7.313 + 7.314 + for(size_t i=0; i<obj->f.size(); i++) { 7.315 + for(int j=0; j<3; j++) { 7.316 + int idx = i * 3 + j; 7.317 + ObjFace *f = &obj->f[i]; 7.318 + 7.319 + varr[idx] = obj->v[f->v[j]]; 7.320 + narr[idx] = obj->vn[f->n[j] < 0 ? 0 : f->n[j]]; 7.321 + 7.322 + float t = obj->vt[f->t[j] < 0 ? 0 : f->t[j]].x; 7.323 + float s = obj->vt[f->t[j] < 0 ? 0 : f->t[j]].y; 7.324 + tarr[idx] = Vector2(t, s); 7.325 + } 7.326 + } 7.327 + 7.328 + if(added_norm) { 7.329 + obj->vn.pop_back(); 7.330 + } 7.331 + if(added_tc) { 7.332 + obj->vt.pop_back(); 7.333 + } 7.334 + 7.335 + Mesh *mesh = robj->get_mesh(); 7.336 + mesh->set_attrib(MESH_ATTR_VERTEX, nelem, 3, &varr->x); 7.337 + mesh->set_attrib(MESH_ATTR_NORMAL, nelem, 3, &narr->x); 7.338 + mesh->set_attrib(MESH_ATTR_TEXCOORD, nelem, 2, &tarr->x); 7.339 + 7.340 + delete [] varr; 7.341 + delete [] narr; 7.342 + delete [] tarr; 7.343 + return robj; 7.344 +} 7.345 + 7.346 +static bool read_materials(FILE *fp, vector<ObjMat> *vmtl) 7.347 +{ 7.348 + ObjMat mat; 7.349 + 7.350 + for(;;) { 7.351 + char line[BUF_SZ]; 7.352 + fgets(line, sizeof line, fp); 7.353 + if(feof(fp)) { 7.354 + break; 7.355 + } 7.356 + 7.357 + char *tok; 7.358 + if(!(tok = strtok(line, SEP))) { 7.359 + continue; 7.360 + } 7.361 + 7.362 + int cmd; 7.363 + if((cmd = get_cmd(tok)) == -1) { 7.364 + continue; 7.365 + } 7.366 + 7.367 + switch(cmd) { 7.368 + case CMD_NEWMTL: 7.369 + // add the previous material, and start a new one 7.370 + if(mat.name.length() > 0) { 7.371 + vmtl->push_back(mat); 7.372 + mat.reset(); 7.373 + } 7.374 + if((tok = strtok(0, SEP))) { 7.375 + mat.name = tok; 7.376 + } 7.377 + break; 7.378 + 7.379 + case CMD_KA: 7.380 + parse_color(&mat.ambient); 7.381 + break; 7.382 + 7.383 + case CMD_KD: 7.384 + parse_color(&mat.diffuse); 7.385 + break; 7.386 + 7.387 + case CMD_KS: 7.388 + parse_color(&mat.specular); 7.389 + break; 7.390 + 7.391 + case CMD_NS: 7.392 + if((tok = strtok(0, SEP)) && is_float(tok)) { 7.393 + mat.shininess = atof(tok); 7.394 + } 7.395 + break; 7.396 + 7.397 + case CMD_NI: 7.398 + if((tok = strtok(0, SEP)) && is_float(tok)) { 7.399 + mat.ior = atof(tok); 7.400 + } 7.401 + break; 7.402 + 7.403 + case CMD_D: 7.404 + case CMD_TR: 7.405 + { 7.406 + Color c; 7.407 + if(parse_color(&c)) { 7.408 + mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; 7.409 + } 7.410 + } 7.411 + break; 7.412 + 7.413 + case CMD_MAP_KD: 7.414 + mat.tex_dif = parse_map(); 7.415 + break; 7.416 + 7.417 + default: 7.418 + break; 7.419 + } 7.420 + } 7.421 + 7.422 + if(mat.name.length() > 0) { 7.423 + vmtl->push_back(mat); 7.424 + } 7.425 + return true; 7.426 +} 7.427 + 7.428 +static int get_cmd(char *str) 7.429 +{ 7.430 + char *s = str; 7.431 + while((*s = toupper(*s))) s++; 7.432 + 7.433 + for(int i=0; cmd_names[i]; i++) { 7.434 + if(strcmp(str, cmd_names[i]) == 0) { 7.435 + return i; 7.436 + } 7.437 + } 7.438 + return CMD_UNK; 7.439 +} 7.440 + 7.441 +static bool is_int(const char *str) 7.442 +{ 7.443 + char *tmp; 7.444 + strtol(str, &tmp, 10); 7.445 + return tmp != str; 7.446 +} 7.447 + 7.448 +static bool is_float(const char *str) 7.449 +{ 7.450 + char *tmp; 7.451 + strtod(str, &tmp); 7.452 + return tmp != str; 7.453 +} 7.454 + 7.455 +static bool parse_vec(Vector3 *vec) 7.456 +{ 7.457 + for(int i=0; i<3; i++) { 7.458 + char *tok; 7.459 + 7.460 + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 7.461 + if(i < 2) { 7.462 + return false; 7.463 + } 7.464 + vec->z = 0.0; 7.465 + } else { 7.466 + (*vec)[i] = atof(tok); 7.467 + } 7.468 + } 7.469 + return true; 7.470 +} 7.471 + 7.472 +static bool parse_color(Color *col) 7.473 +{ 7.474 + for(int i=0; i<3; i++) { 7.475 + char *tok; 7.476 + 7.477 + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 7.478 + col->y = col->z = col->x; 7.479 + return i > 0 ? true : false; 7.480 + } 7.481 + (*col)[i] = atof(tok); 7.482 + } 7.483 + return true; 7.484 +} 7.485 + 7.486 +static bool parse_face(ObjFace *face) 7.487 +{ 7.488 + char *tok[] = {0, 0, 0, 0}; 7.489 + face->elem = 0; 7.490 + 7.491 + for(int i=0; i<4; i++) { 7.492 + if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { 7.493 + if(i < 3) return false; // less than 3 verts? not a polygon 7.494 + } else { 7.495 + face->elem++; 7.496 + } 7.497 + } 7.498 + 7.499 + for(int i=0; i<4; i++) { 7.500 + char *subtok = tok[i]; 7.501 + 7.502 + if(!subtok || !*subtok || !is_int(subtok)) { 7.503 + if(i < 3) { 7.504 + return false; 7.505 + } 7.506 + face->v[i] = INVALID_IDX; 7.507 + } else { 7.508 + face->v[i] = atoi(subtok); 7.509 + if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ 7.510 + } 7.511 + 7.512 + while(subtok && *subtok && *subtok != '/') { 7.513 + subtok++; 7.514 + } 7.515 + if(subtok && *subtok && *++subtok && is_int(subtok)) { 7.516 + face->t[i] = atoi(subtok); 7.517 + if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ 7.518 + } else { 7.519 + face->t[i] = INVALID_IDX; 7.520 + } 7.521 + 7.522 + while(subtok && *subtok && *subtok != '/') { 7.523 + subtok++; 7.524 + } 7.525 + if(subtok && *subtok && *++subtok && is_int(subtok)) { 7.526 + face->n[i] = atoi(subtok); 7.527 + if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ 7.528 + } else { 7.529 + face->n[i] = INVALID_IDX; 7.530 + } 7.531 + } 7.532 + 7.533 + return true; 7.534 +} 7.535 + 7.536 +static const char *parse_map() 7.537 +{ 7.538 + char *tok, *prev = 0; 7.539 + 7.540 + while((tok = strtok(0, SEP))) { 7.541 + prev = tok; 7.542 + } 7.543 + 7.544 + return prev ? prev : ""; 7.545 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/scene.cc Thu Jul 17 02:35:19 2014 +0300 8.3 @@ -0,0 +1,67 @@ 8.4 +#include <stdio.h> 8.5 +#include <stdlib.h> 8.6 +#include "scene.h" 8.7 + 8.8 +Scene::~Scene() 8.9 +{ 8.10 + for(size_t i=0; i<objects.size(); i++) { 8.11 + delete objects[i]; 8.12 + } 8.13 + for(size_t i=0; i<meshes.size(); i++) { 8.14 + delete meshes[i]; 8.15 + } 8.16 +} 8.17 + 8.18 +bool Scene::load(const char *fname) 8.19 +{ 8.20 + FILE *fp = fopen(fname, "rb"); 8.21 + if(!fp) { 8.22 + fprintf(stderr, "failed to open scene file: %s\n", fname); 8.23 + return false; 8.24 + } 8.25 + 8.26 + bool res = load_obj(fp); 8.27 + fclose(fp); 8.28 + return res; 8.29 +} 8.30 + 8.31 +void Scene::add_object(Object *obj) 8.32 +{ 8.33 + objects.push_back(obj); 8.34 +} 8.35 + 8.36 +void Scene::add_mesh(Mesh *mesh) 8.37 +{ 8.38 + meshes.push_back(mesh); 8.39 +} 8.40 + 8.41 +int Scene::get_num_objects() const 8.42 +{ 8.43 + return (int)objects.size(); 8.44 +} 8.45 + 8.46 +int Scene::get_num_meshes() const 8.47 +{ 8.48 + return (int)meshes.size(); 8.49 +} 8.50 + 8.51 +Object *Scene::get_object(int idx) const 8.52 +{ 8.53 + return objects[idx]; 8.54 +} 8.55 + 8.56 +Mesh *Scene::get_mesh(int idx) const 8.57 +{ 8.58 + return meshes[idx]; 8.59 +} 8.60 + 8.61 +void Scene::update(long msec) 8.62 +{ 8.63 +} 8.64 + 8.65 +void Scene::render() const 8.66 +{ 8.67 + for(size_t i=0; i<objects.size(); i++) { 8.68 + objects[i]->render(); 8.69 + } 8.70 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/scene.h Thu Jul 17 02:35:19 2014 +0300 9.3 @@ -0,0 +1,34 @@ 9.4 +#ifndef SCENE_H_ 9.5 +#define SCENE_H_ 9.6 + 9.7 +#include <stdio.h> 9.8 +#include <vector> 9.9 +#include "mesh.h" 9.10 +#include "object.h" 9.11 + 9.12 +class Scene { 9.13 +private: 9.14 + std::vector<Object*> objects; 9.15 + std::vector<Mesh*> meshes; 9.16 + 9.17 + bool load_obj(FILE *fp); // defined in objfile.cc 9.18 + 9.19 +public: 9.20 + ~Scene(); 9.21 + 9.22 + bool load(const char *fname); 9.23 + 9.24 + void add_object(Object *obj); 9.25 + void add_mesh(Mesh *mesh); 9.26 + 9.27 + int get_num_objects() const; 9.28 + int get_num_meshes() const; 9.29 + 9.30 + Object *get_object(int idx) const; 9.31 + Mesh *get_mesh(int idx) const; 9.32 + 9.33 + void update(long msec); 9.34 + void render() const; 9.35 +}; 9.36 + 9.37 +#endif // SCENE_H_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/vmath.h Thu Jul 17 02:35:19 2014 +0300 10.3 @@ -0,0 +1,37 @@ 10.4 +#ifndef VMATH_H_ 10.5 +#define VMATH_H_ 10.6 + 10.7 +class Vector2 { 10.8 +public: 10.9 + float x, y; 10.10 + 10.11 + Vector2() : x(0), y(0) {} 10.12 + Vector2(float xa, float ya) : x(xa), y(ya) {} 10.13 + 10.14 + float &operator [](int idx) { return (&x)[idx]; } 10.15 + const float &operator [](int idx) const { return (&x)[idx]; } 10.16 +}; 10.17 + 10.18 +class Vector3 { 10.19 +public: 10.20 + float x, y, z; 10.21 + 10.22 + Vector3() : x(0), y(0), z(0) {} 10.23 + Vector3(float xa, float ya, float za) : x(xa), y(ya), z(za) {} 10.24 + 10.25 + float &operator [](int idx) { return (&x)[idx]; } 10.26 + const float &operator [](int idx) const { return (&x)[idx]; } 10.27 +}; 10.28 + 10.29 +class Vector4 { 10.30 +public: 10.31 + float x, y, z, w; 10.32 + 10.33 + Vector4() : x(0), y(0), z(0), w(0) {} 10.34 + Vector4(float xa, float ya, float za, float wa) : x(xa), y(ya), z(za), w(wa) {} 10.35 + 10.36 + float &operator [](int idx) { return (&x)[idx]; } 10.37 + const float &operator [](int idx) const { return (&x)[idx]; } 10.38 +}; 10.39 + 10.40 +#endif // VMATH_H_