goat3d
diff src/goat3d.cc @ 16:cb6c1a945a11
goat3d is starting to become functional inch by inch
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 26 Sep 2013 14:16:09 +0300 |
parents | |
children | 1d85d7dd0038 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/goat3d.cc Thu Sep 26 14:16:09 2013 +0300 1.3 @@ -0,0 +1,487 @@ 1.4 +#include <string.h> 1.5 +#include <errno.h> 1.6 +#include "goat3d.h" 1.7 +#include "goat3d_impl.h" 1.8 +#include "log.h" 1.9 + 1.10 +struct goat3d { 1.11 + Scene *scn; 1.12 + unsigned int flags; 1.13 +}; 1.14 + 1.15 +struct goat3d_material : public Material {}; 1.16 +struct goat3d_mesh : public Mesh {}; 1.17 +struct goat3d_light : public Light {}; 1.18 +struct goat3d_camera : public Camera {}; 1.19 +struct goat3d_node : public Node {}; 1.20 + 1.21 + 1.22 +static long read_file(void *buf, size_t bytes, void *uptr); 1.23 +static long write_file(const void *buf, size_t bytes, void *uptr); 1.24 +static long seek_file(long offs, int whence, void *uptr); 1.25 + 1.26 +extern "C" { 1.27 + 1.28 +struct goat3d *goat3d_create(void) 1.29 +{ 1.30 + goat3d *goat = new goat3d; 1.31 + goat->scn = new Scene; 1.32 + return goat; 1.33 +} 1.34 + 1.35 +void goat3d_free(struct goat3d *g) 1.36 +{ 1.37 + delete g->scn; 1.38 + delete g; 1.39 +} 1.40 + 1.41 +void goat3d_setopt(struct goat3d *g, enum goat3d_option opt, int val) 1.42 +{ 1.43 + if(val) { 1.44 + g->flags |= (1 << (int)opt); 1.45 + } else { 1.46 + g->flags &= ~(1 << (int)opt); 1.47 + } 1.48 +} 1.49 + 1.50 +int goat3d_getopt(const struct goat3d *g, enum goat3d_option opt) 1.51 +{ 1.52 + return (g->flags >> (int)opt) & 1; 1.53 +} 1.54 + 1.55 +int goat3d_load(struct goat3d *g, const char *fname) 1.56 +{ 1.57 + FILE *fp = fopen(fname, "rb"); 1.58 + if(!fp) { 1.59 + logmsg(LOG_ERROR, "failed to open file \"%s\" for reading: %s\n", fname, strerror(errno)); 1.60 + return -1; 1.61 + } 1.62 + 1.63 + int res = goat3d_load_file(g, fp); 1.64 + fclose(fp); 1.65 + return res; 1.66 +} 1.67 + 1.68 +int goat3d_save(const struct goat3d *g, const char *fname) 1.69 +{ 1.70 + FILE *fp = fopen(fname, "wb"); 1.71 + if(!fp) { 1.72 + logmsg(LOG_ERROR, "failed to open file \"%s\" for writing: %s\n", fname, strerror(errno)); 1.73 + return -1; 1.74 + } 1.75 + 1.76 + int res = goat3d_save_file(g, fp); 1.77 + fclose(fp); 1.78 + return res; 1.79 +} 1.80 + 1.81 +int goat3d_load_file(struct goat3d *g, FILE *fp) 1.82 +{ 1.83 + goat3d_io io; 1.84 + io.cls = fp; 1.85 + io.read = read_file; 1.86 + io.write = write_file; 1.87 + io.seek = seek_file; 1.88 + 1.89 + return goat3d_load_io(g, &io); 1.90 +} 1.91 + 1.92 +int goat3d_save_file(const struct goat3d *g, FILE *fp) 1.93 +{ 1.94 + goat3d_io io; 1.95 + io.cls = fp; 1.96 + io.read = read_file; 1.97 + io.write = write_file; 1.98 + io.seek = seek_file; 1.99 + 1.100 + return goat3d_save_io(g, &io); 1.101 +} 1.102 + 1.103 +int goat3d_load_io(struct goat3d *g, struct goat3d_io *io) 1.104 +{ 1.105 + if(!g->scn->load(io)) { 1.106 + if(g->scn->loadxml(io)) { 1.107 + return -1; 1.108 + } 1.109 + } 1.110 + return 0; 1.111 +} 1.112 + 1.113 +int goat3d_save_io(const struct goat3d *g, struct goat3d_io *io) 1.114 +{ 1.115 + if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) { 1.116 + return g->scn->savexml(io) ? 0 : -1; 1.117 + } 1.118 + return g->scn->save(io) ? 0 : -1; 1.119 +} 1.120 + 1.121 +int goat3d_set_name(struct goat3d *g, const char *name) 1.122 +{ 1.123 + g->scn->set_name(name); 1.124 + return 0; 1.125 +} 1.126 + 1.127 +const char *goat3d_get_name(const struct goat3d *g) 1.128 +{ 1.129 + return g->scn->get_name(); 1.130 +} 1.131 + 1.132 +void goat3d_set_ambient(struct goat3d *g, const float *amb) 1.133 +{ 1.134 + g->scn->set_ambient(Vector3(amb[0], amb[1], amb[2])); 1.135 +} 1.136 + 1.137 +void goat3d_set_ambient3f(struct goat3d *g, float ar, float ag, float ab) 1.138 +{ 1.139 + g->scn->set_ambient(Vector3(ar, ag, ab)); 1.140 +} 1.141 + 1.142 +const float *goat3d_get_ambient(const struct goat3d *g) 1.143 +{ 1.144 + return &g->scn->get_ambient().x; 1.145 +} 1.146 + 1.147 +// ---- materials ---- 1.148 +struct goat3d_material *goat3d_create_mtl(void) 1.149 +{ 1.150 + return new goat3d_material; 1.151 +} 1.152 + 1.153 +void goat3d_destroy_mtl(struct goat3d_material *mtl) 1.154 +{ 1.155 + delete mtl; 1.156 +} 1.157 + 1.158 +void goat3d_set_mtl_name(struct goat3d_material *mtl, const char *name) 1.159 +{ 1.160 + mtl->name = std::string(name); 1.161 +} 1.162 + 1.163 +const char *goat3d_get_mtl_name(const struct goat3d_material *mtl) 1.164 +{ 1.165 + return mtl->name.c_str(); 1.166 +} 1.167 + 1.168 +void goat3d_set_mtl_attrib(struct goat3d_material *mtl, const char *attrib, const float *val) 1.169 +{ 1.170 + (*mtl)[attrib].value = Vector4(val[0], val[1], val[2], val[3]); 1.171 +} 1.172 + 1.173 +void goat3d_set_mtl_attrib1f(struct goat3d_material *mtl, const char *attrib, float val) 1.174 +{ 1.175 + goat3d_set_mtl_attrib4f(mtl, attrib, val, 0, 0, 1); 1.176 +} 1.177 + 1.178 +void goat3d_set_mtl_attrib3f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b) 1.179 +{ 1.180 + goat3d_set_mtl_attrib4f(mtl, attrib, r, g, b, 1); 1.181 +} 1.182 + 1.183 +void goat3d_set_mtl_attrib4f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b, float a) 1.184 +{ 1.185 + (*mtl)[attrib].value = Vector4(r, g, b, a); 1.186 +} 1.187 + 1.188 +const float *goat3d_get_mtl_attrib(struct goat3d_material *mtl, const char *attrib) 1.189 +{ 1.190 + return &(*mtl)[attrib].value.x; 1.191 +} 1.192 + 1.193 +void goat3d_set_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib, const char *mapname) 1.194 +{ 1.195 + (*mtl)[attrib].map = std::string(mapname); 1.196 +} 1.197 + 1.198 +const char *goat3d_get_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib) 1.199 +{ 1.200 + return (*mtl)[attrib].map.c_str(); 1.201 +} 1.202 + 1.203 +void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl) 1.204 +{ 1.205 + g->scn->add_material(mtl); 1.206 +} 1.207 + 1.208 +// ---- meshes ---- 1.209 +struct goat3d_mesh *goat3d_create_mesh(void) 1.210 +{ 1.211 + return new goat3d_mesh; 1.212 +} 1.213 + 1.214 +void goat3d_destroy_mesh(struct goat3d_mesh *mesh) 1.215 +{ 1.216 + delete mesh; 1.217 +} 1.218 + 1.219 +void goat3d_set_mesh_name(struct goat3d_mesh *mesh, const char *name) 1.220 +{ 1.221 + mesh->name = std::string(name); 1.222 +} 1.223 + 1.224 +const char *goat3d_get_mesh_name(const struct goat3d_mesh *mesh) 1.225 +{ 1.226 + return mesh->name.c_str(); 1.227 +} 1.228 + 1.229 +void goat3d_set_mesh_mtl(struct goat3d_mesh *mesh, struct goat3d_material *mtl) 1.230 +{ 1.231 + mesh->material = mtl; 1.232 +} 1.233 + 1.234 +struct goat3d_material *goat3d_get_mesh_mtl(struct goat3d_mesh *mesh) 1.235 +{ 1.236 + return (goat3d_material*)mesh->material; 1.237 +} 1.238 + 1.239 +int goat3d_get_mesh_attrib_count(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib) 1.240 +{ 1.241 + return (int)mesh->vertices.size(); 1.242 +} 1.243 + 1.244 +int goat3d_get_mesh_face_count(struct goat3d_mesh *mesh) 1.245 +{ 1.246 + return (int)mesh->faces.size(); 1.247 +} 1.248 + 1.249 +#if __cplusplus >= 201103L 1.250 +#define MOVE(x) std::move(x) 1.251 +#else 1.252 +#define MOVE(x) x 1.253 +#endif 1.254 + 1.255 +#define VECDATA(type, data, num) \ 1.256 + MOVE(std::vector<type>((type*)(data), (type*)(data) + (num))) 1.257 + 1.258 +void goat3d_set_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, const void *data, int vnum) 1.259 +{ 1.260 + if(attrib == GOAT3D_MESH_ATTR_VERTEX) { 1.261 + mesh->vertices = VECDATA(Vector3, data, vnum); 1.262 + return; 1.263 + } 1.264 + 1.265 + if(vnum != (int)mesh->vertices.size()) { 1.266 + logmsg(LOG_ERROR, "trying to set mesh attrib data with number of elements different than the vertex array\n"); 1.267 + return; 1.268 + } 1.269 + 1.270 + switch(attrib) { 1.271 + case GOAT3D_MESH_ATTR_NORMAL: 1.272 + mesh->normals = VECDATA(Vector3, data, vnum); 1.273 + break; 1.274 + case GOAT3D_MESH_ATTR_TANGENT: 1.275 + mesh->tangents = VECDATA(Vector3, data, vnum); 1.276 + break; 1.277 + case GOAT3D_MESH_ATTR_TEXCOORD: 1.278 + mesh->texcoords = VECDATA(Vector2, data, vnum); 1.279 + break; 1.280 + case GOAT3D_MESH_ATTR_SKIN_WEIGHT: 1.281 + mesh->skin_weights = VECDATA(Vector4, data, vnum); 1.282 + break; 1.283 + case GOAT3D_MESH_ATTR_SKIN_MATRIX: 1.284 + mesh->skin_matrices = VECDATA(Int4, data, vnum); 1.285 + break; 1.286 + case GOAT3D_MESH_ATTR_COLOR: 1.287 + mesh->colors = VECDATA(Vector4, data, vnum); 1.288 + default: 1.289 + break; 1.290 + } 1.291 +} 1.292 + 1.293 +void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib) 1.294 +{ 1.295 + return goat3d_get_mesh_attrib(mesh, attrib, 0); 1.296 +} 1.297 + 1.298 +void *goat3d_get_mesh_attrib(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, int idx) 1.299 +{ 1.300 + switch(attrib) { 1.301 + case GOAT3D_MESH_ATTR_VERTEX: 1.302 + return mesh->vertices.empty() ? 0 : (void*)&mesh->vertices[idx]; 1.303 + case GOAT3D_MESH_ATTR_NORMAL: 1.304 + return mesh->normals.empty() ? 0 : (void*)&mesh->normals[idx]; 1.305 + case GOAT3D_MESH_ATTR_TANGENT: 1.306 + return mesh->tangents.empty() ? 0 : (void*)&mesh->tangents[idx]; 1.307 + case GOAT3D_MESH_ATTR_TEXCOORD: 1.308 + return mesh->texcoords.empty() ? 0 : (void*)&mesh->texcoords[idx]; 1.309 + case GOAT3D_MESH_ATTR_SKIN_WEIGHT: 1.310 + return mesh->skin_weights.empty() ? 0 : (void*)&mesh->skin_weights[idx]; 1.311 + case GOAT3D_MESH_ATTR_SKIN_MATRIX: 1.312 + return mesh->skin_matrices.empty() ? 0 : (void*)&mesh->skin_matrices[idx]; 1.313 + case GOAT3D_MESH_ATTR_COLOR: 1.314 + return mesh->colors.empty() ? 0 : (void*)&mesh->colors[idx]; 1.315 + default: 1.316 + break; 1.317 + } 1.318 + return 0; 1.319 +} 1.320 + 1.321 + 1.322 +void goat3d_set_mesh_faces(struct goat3d_mesh *mesh, const int *data, int num) 1.323 +{ 1.324 + mesh->faces = VECDATA(Face, data, num); 1.325 +} 1.326 + 1.327 +int *goat3d_get_mesh_faces(struct goat3d_mesh *mesh) 1.328 +{ 1.329 + return goat3d_get_mesh_face(mesh, 0); 1.330 +} 1.331 + 1.332 +int *goat3d_get_mesh_face(struct goat3d_mesh *mesh, int idx) 1.333 +{ 1.334 + return mesh->faces.empty() ? 0 : mesh->faces[idx].v; 1.335 +} 1.336 + 1.337 +// immedate mode state 1.338 +static enum goat3d_im_primitive im_prim; 1.339 +static struct goat3d_mesh *im_mesh; 1.340 +static Vector3 im_norm, im_tang; 1.341 +static Vector2 im_texcoord; 1.342 +static Vector4 im_skinw, im_color = Vector4(1, 1, 1, 1); 1.343 +static Int4 im_skinmat; 1.344 +static bool im_use[NUM_GOAT3D_MESH_ATTRIBS]; 1.345 + 1.346 + 1.347 +void goat3d_begin(struct goat3d_mesh *mesh, enum goat3d_im_primitive prim) 1.348 +{ 1.349 + mesh->vertices.clear(); 1.350 + mesh->normals.clear(); 1.351 + mesh->tangents.clear(); 1.352 + mesh->texcoords.clear(); 1.353 + mesh->skin_weights.clear(); 1.354 + mesh->skin_matrices.clear(); 1.355 + mesh->colors.clear(); 1.356 + mesh->faces.clear(); 1.357 + 1.358 + im_mesh = mesh; 1.359 + memset(im_use, 0, sizeof im_use); 1.360 + 1.361 + im_prim = prim; 1.362 +} 1.363 + 1.364 +void goat3d_end(void) 1.365 +{ 1.366 + static int tri_offs[] = {0, 1, 2}; 1.367 + static int quad_offs[] = {0, 1, 2, 0, 2, 3}; 1.368 + int *index_offs; 1.369 + 1.370 + int num_faces, in_face_verts, out_face_verts; 1.371 + switch(im_prim) { 1.372 + case GOAT3D_TRIANGLES: 1.373 + in_face_verts = 3; 1.374 + out_face_verts = 3; 1.375 + index_offs = tri_offs; 1.376 + break; 1.377 + 1.378 + case GOAT3D_QUADS: 1.379 + in_face_verts = 4; 1.380 + out_face_verts = 6; 1.381 + index_offs = quad_offs; 1.382 + break; 1.383 + 1.384 + default: 1.385 + return; 1.386 + }; 1.387 + 1.388 + num_faces = (int)im_mesh->vertices.size() / in_face_verts; 1.389 + if(!num_faces) { 1.390 + return; 1.391 + } 1.392 + 1.393 + im_mesh->faces.resize(num_faces); 1.394 + 1.395 + int vidx = 0; 1.396 + for(int i=0; i<num_faces; i++) { 1.397 + for(int j=0; j<out_face_verts; j++) { 1.398 + im_mesh->faces[i].v[j] = vidx + index_offs[j]; 1.399 + } 1.400 + vidx += 4; 1.401 + } 1.402 +} 1.403 + 1.404 +void goat3d_vertex3f(float x, float y, float z) 1.405 +{ 1.406 + im_mesh->vertices.push_back(Vector3(x, y, z)); 1.407 + if(im_use[GOAT3D_MESH_ATTR_NORMAL]) { 1.408 + im_mesh->normals.push_back(im_norm); 1.409 + } 1.410 + if(im_use[GOAT3D_MESH_ATTR_TANGENT]) { 1.411 + im_mesh->tangents.push_back(im_tang); 1.412 + } 1.413 + if(im_use[GOAT3D_MESH_ATTR_TEXCOORD]) { 1.414 + im_mesh->texcoords.push_back(im_texcoord); 1.415 + } 1.416 + if(im_use[GOAT3D_MESH_ATTR_SKIN_WEIGHT]) { 1.417 + im_mesh->skin_weights.push_back(im_skinw); 1.418 + } 1.419 + if(im_use[GOAT3D_MESH_ATTR_SKIN_MATRIX]) { 1.420 + im_mesh->skin_matrices.push_back(im_skinmat); 1.421 + } 1.422 + if(im_use[GOAT3D_MESH_ATTR_COLOR]) { 1.423 + im_mesh->colors.push_back(im_color); 1.424 + } 1.425 +} 1.426 + 1.427 +void goat3d_normal3f(float x, float y, float z) 1.428 +{ 1.429 + im_norm = Vector3(x, y, z); 1.430 +} 1.431 + 1.432 +void goat3d_tangent3f(float x, float y, float z) 1.433 +{ 1.434 + im_tang = Vector3(x, y, z); 1.435 +} 1.436 + 1.437 +void goat3d_texcoord2f(float x, float y) 1.438 +{ 1.439 + im_texcoord = Vector2(x, y); 1.440 +} 1.441 + 1.442 +void goat3d_skin_weight4f(float x, float y, float z, float w) 1.443 +{ 1.444 + im_skinw = Vector4(x, y, z, w); 1.445 +} 1.446 + 1.447 +void goat3d_skin_matrix4i(int x, int y, int z, int w) 1.448 +{ 1.449 + im_skinmat.x = x; 1.450 + im_skinmat.y = y; 1.451 + im_skinmat.z = z; 1.452 + im_skinmat.w = w; 1.453 +} 1.454 + 1.455 +void goat3d_color3f(float x, float y, float z) 1.456 +{ 1.457 + im_color = Vector4(x, y, z, 1.0f); 1.458 +} 1.459 + 1.460 +void goat3d_color4f(float x, float y, float z, float w) 1.461 +{ 1.462 + im_color = Vector4(x, y, z, w); 1.463 +} 1.464 + 1.465 +void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh) 1.466 +{ 1.467 + g->scn->add_mesh(mesh); 1.468 +} 1.469 + 1.470 + 1.471 +} // extern "C" 1.472 + 1.473 + 1.474 +static long read_file(void *buf, size_t bytes, void *uptr) 1.475 +{ 1.476 + return (long)fread(buf, 1, bytes, (FILE*)uptr); 1.477 +} 1.478 + 1.479 +static long write_file(const void *buf, size_t bytes, void *uptr) 1.480 +{ 1.481 + return (long)fwrite(buf, 1, bytes, (FILE*)uptr); 1.482 +} 1.483 + 1.484 +static long seek_file(long offs, int whence, void *uptr) 1.485 +{ 1.486 + if(fseek((FILE*)uptr, offs, whence) == -1) { 1.487 + return -1; 1.488 + } 1.489 + return ftell((FILE*)uptr); 1.490 +}