goat3d
diff src/goat3d_writexml.cc @ 14:188c697b3b49
- added a document describing the goat3d file format chunk hierarchy
- started an alternative XML-based file format
- added the openctm library
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 26 Sep 2013 04:47:05 +0300 |
parents | |
children | f1b4c27382ce |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/goat3d_writexml.cc Thu Sep 26 04:47:05 2013 +0300 1.3 @@ -0,0 +1,187 @@ 1.4 +#include <stdarg.h> 1.5 +#include "goat3d_impl.h" 1.6 +#include "chunk.h" 1.7 +#include "openctm.h" 1.8 + 1.9 +static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level); 1.10 +static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level); 1.11 +static void write_ctm_mesh(const Mesh *mesh, const char *fname); 1.12 +static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level); 1.13 +static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level); 1.14 +static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level); 1.15 +static void xmlout(goat3d_io *io, int level, const char *fmt, ...); 1.16 + 1.17 +bool Scene::savexml(goat3d_io *io) const 1.18 +{ 1.19 + xmlout(io, 0, "<scene>\n"); 1.20 + 1.21 + // write environment stuff 1.22 + xmlout(io, 1, "<env>\n"); 1.23 + xmlout(io, 1, "</env>\n"); 1.24 + 1.25 + for(size_t i=0; i<materials.size(); i++) { 1.26 + write_material(this, io, materials[i], 1); 1.27 + } 1.28 + for(size_t i=0; i<meshes.size(); i++) { 1.29 + write_mesh(this, io, meshes[i], i, 1); 1.30 + } 1.31 + for(size_t i=0; i<lights.size(); i++) { 1.32 + write_light(this, io, lights[i], 1); 1.33 + } 1.34 + for(size_t i=0; i<cameras.size(); i++) { 1.35 + write_camera(this, io, cameras[i], 1); 1.36 + } 1.37 + for(size_t i=0; i<nodes.size(); i++) { 1.38 + write_node(this, io, nodes[i], 1); 1.39 + } 1.40 + 1.41 + xmlout(io, 0, "</scene>\n"); 1.42 + return true; 1.43 +} 1.44 + 1.45 +static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level) 1.46 +{ 1.47 + xmlout(io, level, "<mtl>\n"); 1.48 + xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str()); 1.49 + 1.50 + for(int i=0; i<mat->get_attrib_count(); i++) { 1.51 + xmlout(io, level + 1, "<attr>\n"); 1.52 + xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i)); 1.53 + 1.54 + const MaterialAttrib &attr = (*mat)[i]; 1.55 + xmlout(io, level + 2, "<val float4=\"%.3f %.3f %.3f\"/>\n", attr.value.x, 1.56 + attr.value.y, attr.value.z, attr.value.w); 1.57 + if(!attr.map.empty()) { 1.58 + xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str()); 1.59 + } 1.60 + xmlout(io, level + 1, "</attr>\n"); 1.61 + } 1.62 + xmlout(io, level, "</mtl>\n"); 1.63 + return true; 1.64 +} 1.65 + 1.66 +static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level) 1.67 +{ 1.68 + // first write the external (openctm) mesh file 1.69 + const char *prefix = scn->get_name(); 1.70 + if(!prefix) { 1.71 + prefix = "goat"; 1.72 + } 1.73 + 1.74 + char *mesh_filename = (char*)alloca(strlen(prefix) + 32); 1.75 + sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx); 1.76 + 1.77 + write_ctm_mesh(mesh, mesh_filename); 1.78 + 1.79 + // then refer to that filename in the XML tags 1.80 + xmlout(io, level, "<mesh>\n"); 1.81 + xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str()); 1.82 + xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str()); 1.83 + xmlout(io, level + 1, "<file string=\"%s\"/>\n", mesh_filename); 1.84 + xmlout(io, level, "</mesh>\n"); 1.85 + return true; 1.86 +} 1.87 + 1.88 +static void write_ctm_mesh(const Mesh *mesh, const char *fname) 1.89 +{ 1.90 + int vnum = (int)mesh->vertices.size(); 1.91 + 1.92 + CTMcontext ctm = ctmNewContext(CTM_EXPORT); 1.93 + 1.94 + // vertices, normals, and face-vertex indices 1.95 + ctmDefineMesh(ctm, &mesh->vertices[0].x, vnum, (CTMuint*)mesh->faces[0].v, 1.96 + mesh->faces.size(), mesh->normals.empty() ? 0 : &mesh->normals[0].x); 1.97 + 1.98 + // texture coordinates 1.99 + if(!mesh->texcoords.empty()) { 1.100 + CTMfloat *uvarray = new CTMfloat[vnum * 2 * sizeof *uvarray]; 1.101 + CTMfloat *uvptr = uvarray; 1.102 + 1.103 + for(int i=0; i<vnum; i++) { 1.104 + *uvptr++ = mesh->texcoords[i].x; 1.105 + *uvptr++ = mesh->texcoords[i].y; 1.106 + } 1.107 + ctmAddUVMap(ctm, uvarray, "texcoord", 0); 1.108 + delete [] uvarray; 1.109 + } 1.110 + 1.111 + // vertex colors 1.112 + if(!mesh->colors.empty()) { 1.113 + ctmAddAttribMap(ctm, &mesh->colors[0].x, "color"); 1.114 + } 1.115 + 1.116 + // skin weights 1.117 + if(!mesh->skin_weights.empty()) { 1.118 + ctmAddAttribMap(ctm, &mesh->skin_weights[0].x, "skin_weight"); 1.119 + } 1.120 + 1.121 + // if either of the non-float4 attributes are present we need to make a tmp array 1.122 + CTMfloat *attr_array = 0; 1.123 + if(!mesh->tangents.empty() || !mesh->skin_matrices.empty()) { 1.124 + attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array]; 1.125 + } 1.126 + 1.127 + // tangents 1.128 + if(!mesh->tangents.empty()) { 1.129 + CTMfloat *ptr = attr_array; 1.130 + 1.131 + for(int i=0; i<vnum; i++) { 1.132 + *ptr++ = mesh->tangents[i].x; 1.133 + *ptr++ = mesh->tangents[i].y; 1.134 + *ptr++ = mesh->tangents[i].z; 1.135 + *ptr++ = 1.0; 1.136 + } 1.137 + ctmAddAttribMap(ctm, attr_array, "tangent"); 1.138 + } 1.139 + 1.140 + // skin matrix indices (4 per vertex) 1.141 + if(!mesh->skin_matrices.empty()) { 1.142 + CTMfloat *ptr = attr_array; 1.143 + 1.144 + for(int i=0; i<vnum; i++) { 1.145 + *ptr++ = (float)mesh->skin_matrices[i].x; 1.146 + *ptr++ = (float)mesh->skin_matrices[i].y; 1.147 + *ptr++ = (float)mesh->skin_matrices[i].z; 1.148 + *ptr++ = (float)mesh->skin_matrices[i].w; 1.149 + } 1.150 + ctmAddAttribMap(ctm, attr_array, "skin_matrix"); 1.151 + } 1.152 + 1.153 + delete [] attr_array; 1.154 + 1.155 + /* TODO find a way to specify the nodes participating in the skinning of this mesh 1.156 + * probably in the comment field? 1.157 + */ 1.158 + 1.159 + ctmSave(ctm, fname); 1.160 + 1.161 + ctmFreeContext(ctm); 1.162 +} 1.163 + 1.164 +static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level) 1.165 +{ 1.166 + return true; 1.167 +} 1.168 + 1.169 +static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level) 1.170 +{ 1.171 + return true; 1.172 +} 1.173 + 1.174 +static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level) 1.175 +{ 1.176 + return true; 1.177 +} 1.178 + 1.179 + 1.180 +static void xmlout(goat3d_io *io, int level, const char *fmt, ...) 1.181 +{ 1.182 + for(int i=0; i<level; i++) { 1.183 + io_fprintf(io, " "); 1.184 + } 1.185 + 1.186 + va_list ap; 1.187 + va_start(ap, fmt); 1.188 + io_vfprintf(io, fmt, ap); 1.189 + va_end(ap); 1.190 +}