goat3d

view src/goat3d_writexml.cc @ 18:bdfc8dd14965

done with goatprim
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 27 Sep 2013 03:17:36 +0300
parents 1d85d7dd0038
children b35427826b60
line source
1 #include <stdarg.h>
2 #include "goat3d_impl.h"
3 #include "log.h"
4 #include "openctm.h"
6 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
7 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level);
8 static void write_ctm_mesh(const Mesh *mesh, const char *fname);
9 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level);
10 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level);
11 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level);
12 static void xmlout(goat3d_io *io, int level, const char *fmt, ...);
14 bool Scene::savexml(goat3d_io *io) const
15 {
16 xmlout(io, 0, "<scene>\n");
18 // write environment stuff
19 xmlout(io, 1, "<env>\n");
20 xmlout(io, 2, "<ambient float3=\"%g %g %g\"/>\n", ambient.x, ambient.y, ambient.z);
21 xmlout(io, 1, "</env>\n\n");
23 for(size_t i=0; i<materials.size(); i++) {
24 write_material(this, io, materials[i], 1);
25 }
26 for(size_t i=0; i<meshes.size(); i++) {
27 write_mesh(this, io, meshes[i], i, 1);
28 }
29 for(size_t i=0; i<lights.size(); i++) {
30 write_light(this, io, lights[i], 1);
31 }
32 for(size_t i=0; i<cameras.size(); i++) {
33 write_camera(this, io, cameras[i], 1);
34 }
35 for(size_t i=0; i<nodes.size(); i++) {
36 write_node(this, io, nodes[i], 1);
37 }
39 xmlout(io, 0, "</scene>\n");
40 return true;
41 }
43 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level)
44 {
45 xmlout(io, level, "<mtl>\n");
46 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str());
48 for(int i=0; i<mat->get_attrib_count(); i++) {
49 xmlout(io, level + 1, "<attr>\n");
50 xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i));
52 const MaterialAttrib &attr = (*mat)[i];
53 xmlout(io, level + 2, "<val float4=\"%g %g %g %g\"/>\n", attr.value.x,
54 attr.value.y, attr.value.z, attr.value.w);
55 if(!attr.map.empty()) {
56 xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str());
57 }
58 xmlout(io, level + 1, "</attr>\n");
59 }
60 xmlout(io, level, "</mtl>\n\n");
61 return true;
62 }
64 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level)
65 {
66 // first write the external (openctm) mesh file
67 const char *prefix = scn->get_name();
68 if(!prefix) {
69 prefix = "goat";
70 }
72 char *mesh_filename = (char*)alloca(strlen(prefix) + 32);
73 sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx);
75 write_ctm_mesh(mesh, mesh_filename);
77 // then refer to that filename in the XML tags
78 xmlout(io, level, "<mesh>\n");
79 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str());
80 if(mesh->material) {
81 xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
82 }
83 xmlout(io, level + 1, "<file string=\"%s\"/>\n", mesh_filename);
84 xmlout(io, level, "</mesh>\n\n");
85 return true;
86 }
88 static void write_ctm_mesh(const Mesh *mesh, const char *fname)
89 {
90 int vnum = (int)mesh->vertices.size();
92 CTMcontext ctm = ctmNewContext(CTM_EXPORT);
94 // vertices, normals, and face-vertex indices
95 ctmDefineMesh(ctm, &mesh->vertices[0].x, vnum, (CTMuint*)mesh->faces[0].v,
96 mesh->faces.size(), mesh->normals.empty() ? 0 : &mesh->normals[0].x);
98 // texture coordinates
99 if(!mesh->texcoords.empty()) {
100 ctmAddUVMap(ctm, &mesh->texcoords[0].x, "texcoord", 0);
101 }
103 // vertex colors
104 if(!mesh->colors.empty()) {
105 ctmAddAttribMap(ctm, &mesh->colors[0].x, "color");
106 }
108 // skin weights
109 if(!mesh->skin_weights.empty()) {
110 ctmAddAttribMap(ctm, &mesh->skin_weights[0].x, "skin_weight");
111 }
113 // if either of the non-float4 attributes are present we need to make a tmp array
114 CTMfloat *attr_array = 0;
115 if(!mesh->tangents.empty() || !mesh->skin_matrices.empty()) {
116 attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array];
117 }
119 // tangents
120 if(!mesh->tangents.empty()) {
121 CTMfloat *ptr = attr_array;
123 for(int i=0; i<vnum; i++) {
124 *ptr++ = mesh->tangents[i].x;
125 *ptr++ = mesh->tangents[i].y;
126 *ptr++ = mesh->tangents[i].z;
127 *ptr++ = 1.0;
128 }
129 ctmAddAttribMap(ctm, attr_array, "tangent");
130 }
132 // skin matrix indices (4 per vertex)
133 if(!mesh->skin_matrices.empty()) {
134 CTMfloat *ptr = attr_array;
136 for(int i=0; i<vnum; i++) {
137 *ptr++ = (float)mesh->skin_matrices[i].x;
138 *ptr++ = (float)mesh->skin_matrices[i].y;
139 *ptr++ = (float)mesh->skin_matrices[i].z;
140 *ptr++ = (float)mesh->skin_matrices[i].w;
141 }
142 ctmAddAttribMap(ctm, attr_array, "skin_matrix");
143 }
145 delete [] attr_array;
147 /* TODO find a way to specify the nodes participating in the skinning of this mesh
148 * probably in the comment field?
149 */
151 logmsg(LOG_INFO, "saving CTM mesh file: %s\n", fname);
152 ctmSave(ctm, fname);
154 ctmFreeContext(ctm);
155 }
157 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level)
158 {
159 return true;
160 }
162 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level)
163 {
164 return true;
165 }
167 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level)
168 {
169 return true;
170 }
173 static void xmlout(goat3d_io *io, int level, const char *fmt, ...)
174 {
175 for(int i=0; i<level; i++) {
176 io_fprintf(io, " ");
177 }
179 va_list ap;
180 va_start(ap, fmt);
181 io_vfprintf(io, fmt, ap);
182 va_end(ap);
183 }