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