nuclear@16: #include nuclear@16: #include nuclear@31: #include nuclear@31: #include nuclear@16: #include "goat3d.h" nuclear@16: #include "goat3d_impl.h" nuclear@16: #include "log.h" nuclear@16: nuclear@31: #ifndef _MSC_VER nuclear@31: #include nuclear@31: #else nuclear@31: #include nuclear@31: #endif nuclear@31: nuclear@47: using namespace g3dimpl; nuclear@47: nuclear@16: struct goat3d { nuclear@16: Scene *scn; nuclear@16: unsigned int flags; nuclear@32: char *search_path; nuclear@16: }; nuclear@16: nuclear@16: struct goat3d_material : public Material {}; nuclear@16: struct goat3d_mesh : public Mesh {}; nuclear@16: struct goat3d_light : public Light {}; nuclear@16: struct goat3d_camera : public Camera {}; nuclear@16: struct goat3d_node : public Node {}; nuclear@16: nuclear@16: nuclear@16: static long read_file(void *buf, size_t bytes, void *uptr); nuclear@16: static long write_file(const void *buf, size_t bytes, void *uptr); nuclear@16: static long seek_file(long offs, int whence, void *uptr); nuclear@16: nuclear@16: extern "C" { nuclear@16: nuclear@41: GOAT3DAPI struct goat3d *goat3d_create(void) nuclear@16: { nuclear@16: goat3d *goat = new goat3d; nuclear@27: goat->flags = 0; nuclear@32: goat->search_path = 0; nuclear@16: goat->scn = new Scene; nuclear@29: nuclear@29: goat3d_setopt(goat, GOAT3D_OPT_SAVEXML, 1); nuclear@16: return goat; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_free(struct goat3d *g) nuclear@16: { nuclear@32: delete g->search_path; nuclear@16: delete g->scn; nuclear@16: delete g; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_setopt(struct goat3d *g, enum goat3d_option opt, int val) nuclear@16: { nuclear@16: if(val) { nuclear@16: g->flags |= (1 << (int)opt); nuclear@16: } else { nuclear@16: g->flags &= ~(1 << (int)opt); nuclear@16: } nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_getopt(const struct goat3d *g, enum goat3d_option opt) nuclear@16: { nuclear@16: return (g->flags >> (int)opt) & 1; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_load(struct goat3d *g, const char *fname) nuclear@16: { nuclear@16: FILE *fp = fopen(fname, "rb"); nuclear@16: if(!fp) { nuclear@16: logmsg(LOG_ERROR, "failed to open file \"%s\" for reading: %s\n", fname, strerror(errno)); nuclear@16: return -1; nuclear@16: } nuclear@16: nuclear@32: /* if the filename contained any directory components, keep the prefix nuclear@32: * to use it as a search path for external mesh file loading nuclear@32: */ nuclear@32: g->search_path = new char[strlen(fname) + 1]; nuclear@32: strcpy(g->search_path, fname); nuclear@32: nuclear@32: char *slash = strrchr(g->search_path, '/'); nuclear@32: if(slash) { nuclear@32: *slash = 0; nuclear@32: } else { nuclear@32: if((slash = strrchr(g->search_path, '\\'))) { nuclear@32: *slash = 0; nuclear@32: } else { nuclear@32: delete [] g->search_path; nuclear@32: g->search_path = 0; nuclear@32: } nuclear@32: } nuclear@32: nuclear@16: int res = goat3d_load_file(g, fp); nuclear@16: fclose(fp); nuclear@16: return res; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_save(const struct goat3d *g, const char *fname) nuclear@16: { nuclear@16: FILE *fp = fopen(fname, "wb"); nuclear@16: if(!fp) { nuclear@16: logmsg(LOG_ERROR, "failed to open file \"%s\" for writing: %s\n", fname, strerror(errno)); nuclear@16: return -1; nuclear@16: } nuclear@16: nuclear@16: int res = goat3d_save_file(g, fp); nuclear@16: fclose(fp); nuclear@16: return res; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_load_file(struct goat3d *g, FILE *fp) nuclear@16: { nuclear@16: goat3d_io io; nuclear@16: io.cls = fp; nuclear@16: io.read = read_file; nuclear@16: io.write = write_file; nuclear@16: io.seek = seek_file; nuclear@16: nuclear@16: return goat3d_load_io(g, &io); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_save_file(const struct goat3d *g, FILE *fp) nuclear@16: { nuclear@16: goat3d_io io; nuclear@16: io.cls = fp; nuclear@16: io.read = read_file; nuclear@16: io.write = write_file; nuclear@16: io.seek = seek_file; nuclear@16: nuclear@16: return goat3d_save_io(g, &io); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_load_io(struct goat3d *g, struct goat3d_io *io) nuclear@16: { nuclear@16: if(!g->scn->load(io)) { nuclear@45: if(!g->scn->loadxml(io)) { nuclear@16: return -1; nuclear@16: } nuclear@16: } nuclear@16: return 0; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_save_io(const struct goat3d *g, struct goat3d_io *io) nuclear@16: { nuclear@16: if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) { nuclear@16: return g->scn->savexml(io) ? 0 : -1; nuclear@16: } nuclear@16: return g->scn->save(io) ? 0 : -1; nuclear@16: } nuclear@16: nuclear@47: /* save/load animations */ nuclear@47: GOAT3DAPI int goat3d_load_anim(struct goat3d *g, const char *fname) nuclear@47: { nuclear@47: FILE *fp = fopen(fname, "rb"); nuclear@47: if(!fp) { nuclear@47: return -1; nuclear@47: } nuclear@47: nuclear@47: int res = goat3d_load_anim_file(g, fp); nuclear@47: fclose(fp); nuclear@47: return res; nuclear@47: } nuclear@47: nuclear@55: GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const char *fname) nuclear@47: { nuclear@47: FILE *fp = fopen(fname, "wb"); nuclear@47: if(!fp) { nuclear@47: return -1; nuclear@47: } nuclear@47: nuclear@55: int res = goat3d_save_anim_file(g, fp); nuclear@47: fclose(fp); nuclear@47: return res; nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI int goat3d_load_anim_file(struct goat3d *g, FILE *fp) nuclear@47: { nuclear@47: goat3d_io io; nuclear@47: io.cls = fp; nuclear@47: io.read = read_file; nuclear@47: io.write = write_file; nuclear@47: io.seek = seek_file; nuclear@47: nuclear@47: return goat3d_load_anim_io(g, &io); nuclear@47: } nuclear@47: nuclear@55: GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, FILE *fp) nuclear@47: { nuclear@47: goat3d_io io; nuclear@47: io.cls = fp; nuclear@47: io.read = read_file; nuclear@47: io.write = write_file; nuclear@47: io.seek = seek_file; nuclear@47: nuclear@55: return goat3d_save_anim_io(g, &io); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io) nuclear@47: { nuclear@47: if(!g->scn->load_anim(io)) { nuclear@47: if(!g->scn->load_anim_xml(io)) { nuclear@47: return -1; nuclear@47: } nuclear@47: } nuclear@47: return 0; nuclear@47: } nuclear@47: nuclear@55: GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, struct goat3d_io *io) nuclear@47: { nuclear@47: if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) { nuclear@55: return g->scn->save_anim_xml(io) ? 0 : -1; nuclear@47: } nuclear@55: return g->scn->save_anim(io) ? 0 : -1; nuclear@47: } nuclear@47: nuclear@47: nuclear@41: GOAT3DAPI int goat3d_set_name(struct goat3d *g, const char *name) nuclear@16: { nuclear@16: g->scn->set_name(name); nuclear@16: return 0; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI const char *goat3d_get_name(const struct goat3d *g) nuclear@16: { nuclear@16: return g->scn->get_name(); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_ambient(struct goat3d *g, const float *amb) nuclear@16: { nuclear@16: g->scn->set_ambient(Vector3(amb[0], amb[1], amb[2])); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_ambient3f(struct goat3d *g, float ar, float ag, float ab) nuclear@16: { nuclear@16: g->scn->set_ambient(Vector3(ar, ag, ab)); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI const float *goat3d_get_ambient(const struct goat3d *g) nuclear@16: { nuclear@16: return &g->scn->get_ambient().x; nuclear@16: } nuclear@16: nuclear@16: // ---- materials ---- nuclear@41: GOAT3DAPI void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl) nuclear@27: { nuclear@27: g->scn->add_material(mtl); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_material *goat3d_create_mtl(void) nuclear@16: { nuclear@16: return new goat3d_material; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_destroy_mtl(struct goat3d_material *mtl) nuclear@16: { nuclear@16: delete mtl; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mtl_name(struct goat3d_material *mtl, const char *name) nuclear@16: { nuclear@16: mtl->name = std::string(name); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI const char *goat3d_get_mtl_name(const struct goat3d_material *mtl) nuclear@16: { nuclear@16: return mtl->name.c_str(); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mtl_attrib(struct goat3d_material *mtl, const char *attrib, const float *val) nuclear@16: { nuclear@16: (*mtl)[attrib].value = Vector4(val[0], val[1], val[2], val[3]); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mtl_attrib1f(struct goat3d_material *mtl, const char *attrib, float val) nuclear@16: { nuclear@16: goat3d_set_mtl_attrib4f(mtl, attrib, val, 0, 0, 1); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mtl_attrib3f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b) nuclear@16: { nuclear@16: goat3d_set_mtl_attrib4f(mtl, attrib, r, g, b, 1); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mtl_attrib4f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b, float a) nuclear@16: { nuclear@16: (*mtl)[attrib].value = Vector4(r, g, b, a); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI const float *goat3d_get_mtl_attrib(struct goat3d_material *mtl, const char *attrib) nuclear@16: { nuclear@16: return &(*mtl)[attrib].value.x; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib, const char *mapname) nuclear@16: { nuclear@51: (*mtl)[attrib].map = clean_filename(mapname); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI const char *goat3d_get_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib) nuclear@16: { nuclear@16: return (*mtl)[attrib].map.c_str(); nuclear@16: } nuclear@16: nuclear@27: // ---- meshes ---- nuclear@41: GOAT3DAPI void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh) nuclear@16: { nuclear@27: g->scn->add_mesh(mesh); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_get_mesh_count(struct goat3d *g) nuclear@27: { nuclear@27: return g->scn->get_mesh_count(); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_mesh *goat3d_get_mesh(struct goat3d *g, int idx) nuclear@27: { nuclear@27: return (goat3d_mesh*)g->scn->get_mesh(idx); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_mesh *goat3d_get_mesh_by_name(struct goat3d *g, const char *name) nuclear@27: { nuclear@27: return (goat3d_mesh*)g->scn->get_mesh(name); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_mesh *goat3d_create_mesh(void) nuclear@16: { nuclear@16: return new goat3d_mesh; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_destroy_mesh(struct goat3d_mesh *mesh) nuclear@16: { nuclear@16: delete mesh; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mesh_name(struct goat3d_mesh *mesh, const char *name) nuclear@16: { nuclear@16: mesh->name = std::string(name); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI const char *goat3d_get_mesh_name(const struct goat3d_mesh *mesh) nuclear@16: { nuclear@16: return mesh->name.c_str(); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mesh_mtl(struct goat3d_mesh *mesh, struct goat3d_material *mtl) nuclear@16: { nuclear@16: mesh->material = mtl; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI struct goat3d_material *goat3d_get_mesh_mtl(struct goat3d_mesh *mesh) nuclear@16: { nuclear@16: return (goat3d_material*)mesh->material; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_get_mesh_attrib_count(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib) nuclear@16: { nuclear@16: return (int)mesh->vertices.size(); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_get_mesh_face_count(struct goat3d_mesh *mesh) nuclear@16: { nuclear@16: return (int)mesh->faces.size(); nuclear@16: } nuclear@16: nuclear@19: // VECDATA is in goat3d_impl.h nuclear@41: GOAT3DAPI void goat3d_set_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, const void *data, int vnum) nuclear@16: { nuclear@16: if(attrib == GOAT3D_MESH_ATTR_VERTEX) { nuclear@16: mesh->vertices = VECDATA(Vector3, data, vnum); nuclear@16: return; nuclear@16: } nuclear@16: nuclear@16: if(vnum != (int)mesh->vertices.size()) { nuclear@16: logmsg(LOG_ERROR, "trying to set mesh attrib data with number of elements different than the vertex array\n"); nuclear@16: return; nuclear@16: } nuclear@16: nuclear@16: switch(attrib) { nuclear@16: case GOAT3D_MESH_ATTR_NORMAL: nuclear@16: mesh->normals = VECDATA(Vector3, data, vnum); nuclear@16: break; nuclear@16: case GOAT3D_MESH_ATTR_TANGENT: nuclear@16: mesh->tangents = VECDATA(Vector3, data, vnum); nuclear@16: break; nuclear@16: case GOAT3D_MESH_ATTR_TEXCOORD: nuclear@16: mesh->texcoords = VECDATA(Vector2, data, vnum); nuclear@16: break; nuclear@16: case GOAT3D_MESH_ATTR_SKIN_WEIGHT: nuclear@16: mesh->skin_weights = VECDATA(Vector4, data, vnum); nuclear@16: break; nuclear@16: case GOAT3D_MESH_ATTR_SKIN_MATRIX: nuclear@16: mesh->skin_matrices = VECDATA(Int4, data, vnum); nuclear@16: break; nuclear@16: case GOAT3D_MESH_ATTR_COLOR: nuclear@16: mesh->colors = VECDATA(Vector4, data, vnum); nuclear@16: default: nuclear@16: break; nuclear@16: } nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_add_mesh_attrib1f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, nuclear@40: float val) nuclear@40: { nuclear@40: goat3d_add_mesh_attrib4f(mesh, attrib, val, 0, 0, 1); nuclear@40: } nuclear@40: nuclear@41: GOAT3DAPI void goat3d_add_mesh_attrib3f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, nuclear@40: float x, float y, float z) nuclear@40: { nuclear@40: goat3d_add_mesh_attrib4f(mesh, attrib, x, y, z, 1); nuclear@40: } nuclear@40: nuclear@41: GOAT3DAPI void goat3d_add_mesh_attrib4f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, nuclear@40: float x, float y, float z, float w) nuclear@40: { nuclear@40: switch(attrib) { nuclear@40: case GOAT3D_MESH_ATTR_VERTEX: nuclear@40: mesh->vertices.push_back(Vector3(x, y, z)); nuclear@40: break; nuclear@40: case GOAT3D_MESH_ATTR_NORMAL: nuclear@40: mesh->normals.push_back(Vector3(x, y, z)); nuclear@40: break; nuclear@40: case GOAT3D_MESH_ATTR_TANGENT: nuclear@40: mesh->tangents.push_back(Vector3(x, y, z)); nuclear@40: break; nuclear@40: case GOAT3D_MESH_ATTR_TEXCOORD: nuclear@40: mesh->texcoords.push_back(Vector2(x, y)); nuclear@40: break; nuclear@40: case GOAT3D_MESH_ATTR_SKIN_WEIGHT: nuclear@40: mesh->skin_weights.push_back(Vector4(x, y, z, w)); nuclear@40: break; nuclear@40: case GOAT3D_MESH_ATTR_SKIN_MATRIX: nuclear@40: mesh->skin_matrices.push_back(Int4(x, y, z, w)); nuclear@40: break; nuclear@40: case GOAT3D_MESH_ATTR_COLOR: nuclear@40: mesh->colors.push_back(Vector4(x, y, z, w)); nuclear@40: default: nuclear@40: break; nuclear@40: } nuclear@40: } nuclear@40: nuclear@41: GOAT3DAPI void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib) nuclear@16: { nuclear@16: return goat3d_get_mesh_attrib(mesh, attrib, 0); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void *goat3d_get_mesh_attrib(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, int idx) nuclear@16: { nuclear@16: switch(attrib) { nuclear@16: case GOAT3D_MESH_ATTR_VERTEX: nuclear@16: return mesh->vertices.empty() ? 0 : (void*)&mesh->vertices[idx]; nuclear@16: case GOAT3D_MESH_ATTR_NORMAL: nuclear@16: return mesh->normals.empty() ? 0 : (void*)&mesh->normals[idx]; nuclear@16: case GOAT3D_MESH_ATTR_TANGENT: nuclear@16: return mesh->tangents.empty() ? 0 : (void*)&mesh->tangents[idx]; nuclear@16: case GOAT3D_MESH_ATTR_TEXCOORD: nuclear@16: return mesh->texcoords.empty() ? 0 : (void*)&mesh->texcoords[idx]; nuclear@16: case GOAT3D_MESH_ATTR_SKIN_WEIGHT: nuclear@16: return mesh->skin_weights.empty() ? 0 : (void*)&mesh->skin_weights[idx]; nuclear@16: case GOAT3D_MESH_ATTR_SKIN_MATRIX: nuclear@16: return mesh->skin_matrices.empty() ? 0 : (void*)&mesh->skin_matrices[idx]; nuclear@16: case GOAT3D_MESH_ATTR_COLOR: nuclear@16: return mesh->colors.empty() ? 0 : (void*)&mesh->colors[idx]; nuclear@16: default: nuclear@16: break; nuclear@16: } nuclear@16: return 0; nuclear@16: } nuclear@16: nuclear@16: nuclear@41: GOAT3DAPI void goat3d_set_mesh_faces(struct goat3d_mesh *mesh, const int *data, int num) nuclear@16: { nuclear@16: mesh->faces = VECDATA(Face, data, num); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_add_mesh_face(struct goat3d_mesh *mesh, int a, int b, int c) nuclear@40: { nuclear@40: Face face; nuclear@40: face.v[0] = a; nuclear@40: face.v[1] = b; nuclear@40: face.v[2] = c; nuclear@40: mesh->faces.push_back(face); nuclear@40: } nuclear@40: nuclear@41: GOAT3DAPI int *goat3d_get_mesh_faces(struct goat3d_mesh *mesh) nuclear@16: { nuclear@16: return goat3d_get_mesh_face(mesh, 0); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int *goat3d_get_mesh_face(struct goat3d_mesh *mesh, int idx) nuclear@16: { nuclear@16: return mesh->faces.empty() ? 0 : mesh->faces[idx].v; nuclear@16: } nuclear@16: nuclear@16: // immedate mode state nuclear@16: static enum goat3d_im_primitive im_prim; nuclear@16: static struct goat3d_mesh *im_mesh; nuclear@16: static Vector3 im_norm, im_tang; nuclear@16: static Vector2 im_texcoord; nuclear@16: static Vector4 im_skinw, im_color = Vector4(1, 1, 1, 1); nuclear@16: static Int4 im_skinmat; nuclear@16: static bool im_use[NUM_GOAT3D_MESH_ATTRIBS]; nuclear@16: nuclear@16: nuclear@41: GOAT3DAPI void goat3d_begin(struct goat3d_mesh *mesh, enum goat3d_im_primitive prim) nuclear@16: { nuclear@16: mesh->vertices.clear(); nuclear@16: mesh->normals.clear(); nuclear@16: mesh->tangents.clear(); nuclear@16: mesh->texcoords.clear(); nuclear@16: mesh->skin_weights.clear(); nuclear@16: mesh->skin_matrices.clear(); nuclear@16: mesh->colors.clear(); nuclear@16: mesh->faces.clear(); nuclear@16: nuclear@16: im_mesh = mesh; nuclear@16: memset(im_use, 0, sizeof im_use); nuclear@16: nuclear@16: im_prim = prim; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_end(void) nuclear@16: { nuclear@16: switch(im_prim) { nuclear@16: case GOAT3D_TRIANGLES: nuclear@17: { nuclear@17: int num_faces = (int)im_mesh->vertices.size() / 3; nuclear@17: im_mesh->faces.resize(num_faces); nuclear@17: nuclear@17: int vidx = 0; nuclear@17: for(int i=0; ifaces[i].v[0] = vidx++; nuclear@17: im_mesh->faces[i].v[1] = vidx++; nuclear@17: im_mesh->faces[i].v[2] = vidx++; nuclear@17: } nuclear@17: } nuclear@16: break; nuclear@16: nuclear@16: case GOAT3D_QUADS: nuclear@17: { nuclear@17: int num_quads = (int)im_mesh->vertices.size() / 4; nuclear@17: im_mesh->faces.resize(num_quads * 2); nuclear@17: nuclear@17: int vidx = 0; nuclear@17: for(int i=0; ifaces[i * 2].v[0] = vidx; nuclear@17: im_mesh->faces[i * 2].v[1] = vidx + 1; nuclear@17: im_mesh->faces[i * 2].v[2] = vidx + 2; nuclear@17: nuclear@17: im_mesh->faces[i * 2 + 1].v[0] = vidx; nuclear@17: im_mesh->faces[i * 2 + 1].v[1] = vidx + 2; nuclear@17: im_mesh->faces[i * 2 + 1].v[2] = vidx + 3; nuclear@17: nuclear@17: vidx += 4; nuclear@17: } nuclear@17: } nuclear@16: break; nuclear@16: nuclear@16: default: nuclear@16: return; nuclear@16: }; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_vertex3f(float x, float y, float z) nuclear@16: { nuclear@16: im_mesh->vertices.push_back(Vector3(x, y, z)); nuclear@16: if(im_use[GOAT3D_MESH_ATTR_NORMAL]) { nuclear@16: im_mesh->normals.push_back(im_norm); nuclear@16: } nuclear@16: if(im_use[GOAT3D_MESH_ATTR_TANGENT]) { nuclear@16: im_mesh->tangents.push_back(im_tang); nuclear@16: } nuclear@16: if(im_use[GOAT3D_MESH_ATTR_TEXCOORD]) { nuclear@16: im_mesh->texcoords.push_back(im_texcoord); nuclear@16: } nuclear@16: if(im_use[GOAT3D_MESH_ATTR_SKIN_WEIGHT]) { nuclear@16: im_mesh->skin_weights.push_back(im_skinw); nuclear@16: } nuclear@16: if(im_use[GOAT3D_MESH_ATTR_SKIN_MATRIX]) { nuclear@16: im_mesh->skin_matrices.push_back(im_skinmat); nuclear@16: } nuclear@16: if(im_use[GOAT3D_MESH_ATTR_COLOR]) { nuclear@16: im_mesh->colors.push_back(im_color); nuclear@16: } nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_normal3f(float x, float y, float z) nuclear@16: { nuclear@16: im_norm = Vector3(x, y, z); nuclear@17: im_use[GOAT3D_MESH_ATTR_NORMAL] = true; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_tangent3f(float x, float y, float z) nuclear@16: { nuclear@16: im_tang = Vector3(x, y, z); nuclear@17: im_use[GOAT3D_MESH_ATTR_TANGENT] = true; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_texcoord2f(float x, float y) nuclear@16: { nuclear@16: im_texcoord = Vector2(x, y); nuclear@17: im_use[GOAT3D_MESH_ATTR_TEXCOORD] = true; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_skin_weight4f(float x, float y, float z, float w) nuclear@16: { nuclear@16: im_skinw = Vector4(x, y, z, w); nuclear@17: im_use[GOAT3D_MESH_ATTR_SKIN_WEIGHT] = true; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_skin_matrix4i(int x, int y, int z, int w) nuclear@16: { nuclear@16: im_skinmat.x = x; nuclear@16: im_skinmat.y = y; nuclear@16: im_skinmat.z = z; nuclear@16: im_skinmat.w = w; nuclear@17: im_use[GOAT3D_MESH_ATTR_SKIN_MATRIX] = true; nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_color3f(float x, float y, float z) nuclear@16: { nuclear@17: goat3d_color4f(x, y, z, 1.0f); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI void goat3d_color4f(float x, float y, float z, float w) nuclear@16: { nuclear@16: im_color = Vector4(x, y, z, w); nuclear@17: im_use[GOAT3D_MESH_ATTR_COLOR] = true; nuclear@16: } nuclear@16: nuclear@27: /* lights */ nuclear@41: GOAT3DAPI void goat3d_add_light(struct goat3d *g, struct goat3d_light *lt) nuclear@16: { nuclear@27: g->scn->add_light(lt); nuclear@16: } nuclear@16: nuclear@41: GOAT3DAPI int goat3d_get_light_count(struct goat3d *g) nuclear@19: { nuclear@27: return g->scn->get_light_count(); nuclear@19: } nuclear@19: nuclear@41: GOAT3DAPI struct goat3d_light *goat3d_get_light(struct goat3d *g, int idx) nuclear@19: { nuclear@27: return (goat3d_light*)g->scn->get_light(idx); nuclear@19: } nuclear@19: nuclear@41: GOAT3DAPI struct goat3d_light *goat3d_get_light_by_name(struct goat3d *g, const char *name) nuclear@27: { nuclear@27: return (goat3d_light*)g->scn->get_light(name); nuclear@27: } nuclear@27: nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_light *goat3d_create_light(void) nuclear@27: { nuclear@27: return new goat3d_light; nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI void goat3d_destroy_light(struct goat3d_light *lt) nuclear@27: { nuclear@27: delete lt; nuclear@27: } nuclear@27: nuclear@27: nuclear@27: /* cameras */ nuclear@41: GOAT3DAPI void goat3d_add_camera(struct goat3d *g, struct goat3d_camera *cam) nuclear@27: { nuclear@27: g->scn->add_camera(cam); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI int goat3d_get_camera_count(struct goat3d *g) nuclear@27: { nuclear@27: return g->scn->get_camera_count(); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_camera *goat3d_get_camera(struct goat3d *g, int idx) nuclear@27: { nuclear@27: return (goat3d_camera*)g->scn->get_camera(idx); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_camera *goat3d_get_camera_by_name(struct goat3d *g, const char *name) nuclear@27: { nuclear@27: return (goat3d_camera*)g->scn->get_camera(name); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_camera *goat3d_create_camera(void) nuclear@27: { nuclear@27: return new goat3d_camera; nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI void goat3d_destroy_camera(struct goat3d_camera *cam) nuclear@27: { nuclear@27: delete cam; nuclear@27: } nuclear@27: nuclear@27: nuclear@16: nuclear@25: // node nuclear@41: GOAT3DAPI void goat3d_add_node(struct goat3d *g, struct goat3d_node *node) nuclear@27: { nuclear@27: g->scn->add_node(node); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI int goat3d_get_node_count(struct goat3d *g) nuclear@27: { nuclear@27: return g->scn->get_node_count(); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_node *goat3d_get_node(struct goat3d *g, int idx) nuclear@27: { nuclear@27: return (goat3d_node*)g->scn->get_node(idx); nuclear@27: } nuclear@27: nuclear@41: GOAT3DAPI struct goat3d_node *goat3d_get_node_by_name(struct goat3d *g, const char *name) nuclear@27: { nuclear@27: return (goat3d_node*)g->scn->get_node(name); nuclear@27: } nuclear@25: nuclear@41: GOAT3DAPI struct goat3d_node *goat3d_create_node(void) nuclear@25: { nuclear@25: return new goat3d_node; nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_set_node_name(struct goat3d_node *node, const char *name) nuclear@25: { nuclear@25: node->set_name(name); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI const char *goat3d_get_node_name(const struct goat3d_node *node) nuclear@25: { nuclear@25: return node->get_name(); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_set_node_object(struct goat3d_node *node, enum goat3d_node_type type, void *obj) nuclear@25: { nuclear@25: node->set_object((Object*)obj); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void *goat3d_get_node_object(const struct goat3d_node *node) nuclear@25: { nuclear@26: return (void*)node->get_object(); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI enum goat3d_node_type goat3d_get_node_type(const struct goat3d_node *node) nuclear@25: { nuclear@26: const Object *obj = node->get_object(); nuclear@26: if(dynamic_cast(obj)) { nuclear@26: return GOAT3D_NODE_MESH; nuclear@26: } nuclear@26: if(dynamic_cast(obj)) { nuclear@26: return GOAT3D_NODE_LIGHT; nuclear@26: } nuclear@26: if(dynamic_cast(obj)) { nuclear@26: return GOAT3D_NODE_CAMERA; nuclear@26: } nuclear@26: nuclear@26: return GOAT3D_NODE_NULL; nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_add_node_child(struct goat3d_node *node, struct goat3d_node *child) nuclear@25: { nuclear@26: node->add_child(node); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI int goat3d_get_node_child_count(const struct goat3d_node *node) nuclear@25: { nuclear@26: return node->get_children_count(); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI struct goat3d_node *goat3d_get_node_child(const struct goat3d_node *node, int idx) nuclear@25: { nuclear@26: return (goat3d_node*)node->get_child(idx); nuclear@25: } nuclear@25: nuclear@47: GOAT3DAPI struct goat3d_node *goat3d_get_node_parent(const struct goat3d_node *node) nuclear@47: { nuclear@47: return (goat3d_node*)node->get_parent(); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI void goat3d_use_anim(struct goat3d_node *node, int idx) nuclear@47: { nuclear@47: node->use_animation(idx); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI void goat3d_use_anims(struct goat3d_node *node, int aidx, int bidx, float t) nuclear@47: { nuclear@47: node->use_animation(aidx, bidx, t); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI void goat3d_use_anim_by_name(struct goat3d_node *node, const char *name) nuclear@47: { nuclear@47: node->use_animation(name); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI void goat3d_use_anims_by_name(struct goat3d_node *node, const char *aname, const char *bname, float t) nuclear@47: { nuclear@47: node->use_animation(aname, bname, t); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI int goat3d_get_active_anim(struct goat3d_node *node, int which) nuclear@47: { nuclear@47: return node->get_active_animation_index(which); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI float goat3d_get_active_anim_mix(struct goat3d_node *node) nuclear@47: { nuclear@47: return node->get_active_animation_mix(); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI int goat3d_get_anim_count(struct goat3d_node *node) nuclear@47: { nuclear@47: return node->get_animation_count(); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI void goat3d_add_anim(struct goat3d_node *root) nuclear@47: { nuclear@47: root->add_animation(); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI void goat3d_set_anim_name(struct goat3d_node *root, const char *name) nuclear@47: { nuclear@47: root->set_animation_name(name); nuclear@47: } nuclear@47: nuclear@47: GOAT3DAPI const char *goat3d_get_anim_name(struct goat3d_node *node) nuclear@47: { nuclear@47: return node->get_animation_name(); nuclear@47: } nuclear@47: nuclear@41: GOAT3DAPI void goat3d_set_node_position(struct goat3d_node *node, float x, float y, float z, long tmsec) nuclear@25: { nuclear@26: node->set_position(Vector3(x, y, z), tmsec); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_set_node_rotation(struct goat3d_node *node, float qx, float qy, float qz, float qw, long tmsec) nuclear@25: { nuclear@26: node->set_rotation(Quaternion(qw, qx, qy, qz), tmsec); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_set_node_scaling(struct goat3d_node *node, float sx, float sy, float sz, long tmsec) nuclear@25: { nuclear@26: node->set_scaling(Vector3(sx, sy, sz), tmsec); nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_set_node_pivot(struct goat3d_node *node, float px, float py, float pz) nuclear@25: { nuclear@26: node->set_pivot(Vector3(px, py, pz)); nuclear@25: } nuclear@25: nuclear@25: nuclear@41: GOAT3DAPI void goat3d_get_node_position(const struct goat3d_node *node, float *xptr, float *yptr, float *zptr, long tmsec) nuclear@25: { nuclear@26: Vector3 pos = node->get_position(tmsec); nuclear@26: *xptr = pos.x; nuclear@26: *yptr = pos.y; nuclear@26: *zptr = pos.z; nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_get_node_rotation(const struct goat3d_node *node, float *xptr, float *yptr, float *zptr, float *wptr, long tmsec) nuclear@25: { nuclear@26: Quaternion q = node->get_rotation(tmsec); nuclear@26: *xptr = q.v.x; nuclear@26: *yptr = q.v.y; nuclear@26: *zptr = q.v.z; nuclear@26: *wptr = q.s; nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_get_node_scaling(const struct goat3d_node *node, float *xptr, float *yptr, float *zptr, long tmsec) nuclear@25: { nuclear@26: Vector3 scale = node->get_scaling(tmsec); nuclear@26: *xptr = scale.x; nuclear@26: *yptr = scale.y; nuclear@26: *zptr = scale.z; nuclear@25: } nuclear@25: nuclear@41: GOAT3DAPI void goat3d_get_node_pivot(const struct goat3d_node *node, float *xptr, float *yptr, float *zptr) nuclear@25: { nuclear@26: Vector3 pivot = node->get_pivot(); nuclear@26: *xptr = pivot.x; nuclear@26: *yptr = pivot.y; nuclear@26: *zptr = pivot.z; nuclear@25: } nuclear@25: nuclear@25: nuclear@41: GOAT3DAPI void goat3d_get_node_matrix(const struct goat3d_node *node, float *matrix, long tmsec) nuclear@25: { nuclear@26: node->get_xform(tmsec, (Matrix4x4*)matrix); nuclear@25: } nuclear@25: nuclear@25: nuclear@16: } // extern "C" nuclear@16: nuclear@16: nuclear@16: static long read_file(void *buf, size_t bytes, void *uptr) nuclear@16: { nuclear@16: return (long)fread(buf, 1, bytes, (FILE*)uptr); nuclear@16: } nuclear@16: nuclear@16: static long write_file(const void *buf, size_t bytes, void *uptr) nuclear@16: { nuclear@16: return (long)fwrite(buf, 1, bytes, (FILE*)uptr); nuclear@16: } nuclear@16: nuclear@16: static long seek_file(long offs, int whence, void *uptr) nuclear@16: { nuclear@16: if(fseek((FILE*)uptr, offs, whence) == -1) { nuclear@16: return -1; nuclear@16: } nuclear@16: return ftell((FILE*)uptr); nuclear@16: } nuclear@31: nuclear@51: std::string g3dimpl::clean_filename(const char *str) nuclear@31: { nuclear@31: const char *last_slash = strrchr(str, '/'); nuclear@31: if(!last_slash) { nuclear@31: last_slash = strrchr(str, '\\'); nuclear@31: } nuclear@31: nuclear@31: if(last_slash) { nuclear@31: str = last_slash + 1; nuclear@31: } nuclear@31: nuclear@31: char *buf = (char*)alloca(strlen(str) + 1); nuclear@31: char *dest = buf; nuclear@31: while(*str) { nuclear@31: char c = *str++; nuclear@31: *dest++ = tolower(c); nuclear@31: } nuclear@40: *dest = 0; nuclear@31: return buf; nuclear@31: }