nuclear@14: #include nuclear@14: #include "goat3d_impl.h" nuclear@14: #include "chunk.h" nuclear@14: #include "openctm.h" nuclear@14: nuclear@14: static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level); nuclear@14: static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level); nuclear@14: static void write_ctm_mesh(const Mesh *mesh, const char *fname); nuclear@14: static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level); nuclear@14: static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level); nuclear@14: static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level); nuclear@14: static void xmlout(goat3d_io *io, int level, const char *fmt, ...); nuclear@14: nuclear@14: bool Scene::savexml(goat3d_io *io) const nuclear@14: { nuclear@14: xmlout(io, 0, "\n"); nuclear@14: nuclear@14: // write environment stuff nuclear@14: xmlout(io, 1, "\n"); nuclear@14: xmlout(io, 1, "\n"); nuclear@14: nuclear@14: for(size_t i=0; i\n"); nuclear@14: return true; nuclear@14: } nuclear@14: nuclear@14: static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level) nuclear@14: { nuclear@14: xmlout(io, level, "\n"); nuclear@14: xmlout(io, level + 1, "\n", mat->name.c_str()); nuclear@14: nuclear@14: for(int i=0; iget_attrib_count(); i++) { nuclear@14: xmlout(io, level + 1, "\n"); nuclear@14: xmlout(io, level + 2, "\n", mat->get_attrib_name(i)); nuclear@14: nuclear@14: const MaterialAttrib &attr = (*mat)[i]; nuclear@15: xmlout(io, level + 2, "\n", attr.value.x, nuclear@14: attr.value.y, attr.value.z, attr.value.w); nuclear@14: if(!attr.map.empty()) { nuclear@14: xmlout(io, level + 2, "\n", attr.map.c_str()); nuclear@14: } nuclear@14: xmlout(io, level + 1, "\n"); nuclear@14: } nuclear@14: xmlout(io, level, "\n"); nuclear@14: return true; nuclear@14: } nuclear@14: nuclear@14: static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level) nuclear@14: { nuclear@14: // first write the external (openctm) mesh file nuclear@14: const char *prefix = scn->get_name(); nuclear@14: if(!prefix) { nuclear@14: prefix = "goat"; nuclear@14: } nuclear@14: nuclear@14: char *mesh_filename = (char*)alloca(strlen(prefix) + 32); nuclear@14: sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx); nuclear@14: nuclear@14: write_ctm_mesh(mesh, mesh_filename); nuclear@14: nuclear@14: // then refer to that filename in the XML tags nuclear@14: xmlout(io, level, "\n"); nuclear@14: xmlout(io, level + 1, "\n", mesh->name.c_str()); nuclear@14: xmlout(io, level + 1, "\n", mesh->material->name.c_str()); nuclear@14: xmlout(io, level + 1, "\n", mesh_filename); nuclear@14: xmlout(io, level, "\n"); nuclear@14: return true; nuclear@14: } nuclear@14: nuclear@14: static void write_ctm_mesh(const Mesh *mesh, const char *fname) nuclear@14: { nuclear@14: int vnum = (int)mesh->vertices.size(); nuclear@14: nuclear@14: CTMcontext ctm = ctmNewContext(CTM_EXPORT); nuclear@14: nuclear@14: // vertices, normals, and face-vertex indices nuclear@14: ctmDefineMesh(ctm, &mesh->vertices[0].x, vnum, (CTMuint*)mesh->faces[0].v, nuclear@14: mesh->faces.size(), mesh->normals.empty() ? 0 : &mesh->normals[0].x); nuclear@14: nuclear@14: // texture coordinates nuclear@14: if(!mesh->texcoords.empty()) { nuclear@15: ctmAddUVMap(ctm, &mesh->texcoords[0].x, "texcoord", 0); nuclear@14: } nuclear@14: nuclear@14: // vertex colors nuclear@14: if(!mesh->colors.empty()) { nuclear@14: ctmAddAttribMap(ctm, &mesh->colors[0].x, "color"); nuclear@14: } nuclear@14: nuclear@14: // skin weights nuclear@14: if(!mesh->skin_weights.empty()) { nuclear@14: ctmAddAttribMap(ctm, &mesh->skin_weights[0].x, "skin_weight"); nuclear@14: } nuclear@14: nuclear@14: // if either of the non-float4 attributes are present we need to make a tmp array nuclear@14: CTMfloat *attr_array = 0; nuclear@14: if(!mesh->tangents.empty() || !mesh->skin_matrices.empty()) { nuclear@14: attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array]; nuclear@14: } nuclear@14: nuclear@14: // tangents nuclear@14: if(!mesh->tangents.empty()) { nuclear@14: CTMfloat *ptr = attr_array; nuclear@14: nuclear@14: for(int i=0; itangents[i].x; nuclear@14: *ptr++ = mesh->tangents[i].y; nuclear@14: *ptr++ = mesh->tangents[i].z; nuclear@14: *ptr++ = 1.0; nuclear@14: } nuclear@14: ctmAddAttribMap(ctm, attr_array, "tangent"); nuclear@14: } nuclear@14: nuclear@14: // skin matrix indices (4 per vertex) nuclear@14: if(!mesh->skin_matrices.empty()) { nuclear@14: CTMfloat *ptr = attr_array; nuclear@14: nuclear@14: for(int i=0; iskin_matrices[i].x; nuclear@14: *ptr++ = (float)mesh->skin_matrices[i].y; nuclear@14: *ptr++ = (float)mesh->skin_matrices[i].z; nuclear@14: *ptr++ = (float)mesh->skin_matrices[i].w; nuclear@14: } nuclear@14: ctmAddAttribMap(ctm, attr_array, "skin_matrix"); nuclear@14: } nuclear@14: nuclear@14: delete [] attr_array; nuclear@14: nuclear@14: /* TODO find a way to specify the nodes participating in the skinning of this mesh nuclear@14: * probably in the comment field? nuclear@14: */ nuclear@14: nuclear@14: ctmSave(ctm, fname); nuclear@14: nuclear@14: ctmFreeContext(ctm); nuclear@14: } nuclear@14: nuclear@14: static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level) nuclear@14: { nuclear@14: return true; nuclear@14: } nuclear@14: nuclear@14: static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level) nuclear@14: { nuclear@14: return true; nuclear@14: } nuclear@14: nuclear@14: static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level) nuclear@14: { nuclear@14: return true; nuclear@14: } nuclear@14: nuclear@14: nuclear@14: static void xmlout(goat3d_io *io, int level, const char *fmt, ...) nuclear@14: { nuclear@14: for(int i=0; i