goat3d

view src/goat3d_writexml.cc @ 54:dad392c710df

added copyright headers and license files + readme
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 17 Apr 2014 08:50:36 +0300
parents fa5c52ea9d59
children 99715321ad6d
line source
1 /*
2 goat3d - 3D scene, character, and animation file format library.
3 Copyright (C) 2013-2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <list>
19 #include <stdarg.h>
20 #include "goat3d_impl.h"
21 #include "anim/anim.h"
22 #include "log.h"
24 using namespace g3dimpl;
26 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
27 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level);
28 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level);
29 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level);
30 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level);
31 static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level);
32 static void xmlout(goat3d_io *io, int level, const char *fmt, ...);
34 bool Scene::savexml(goat3d_io *io) const
35 {
36 xmlout(io, 0, "<scene>\n");
38 // write environment stuff
39 xmlout(io, 1, "<env>\n");
40 xmlout(io, 2, "<ambient float3=\"%g %g %g\"/>\n", ambient.x, ambient.y, ambient.z);
41 xmlout(io, 1, "</env>\n\n");
43 for(size_t i=0; i<materials.size(); i++) {
44 write_material(this, io, materials[i], 1);
45 }
46 for(size_t i=0; i<meshes.size(); i++) {
47 write_mesh(this, io, meshes[i], i, 1);
48 }
49 for(size_t i=0; i<lights.size(); i++) {
50 write_light(this, io, lights[i], 1);
51 }
52 for(size_t i=0; i<cameras.size(); i++) {
53 write_camera(this, io, cameras[i], 1);
54 }
55 for(size_t i=0; i<nodes.size(); i++) {
56 write_node(this, io, nodes[i], 1);
57 }
59 xmlout(io, 0, "</scene>\n");
60 return true;
61 }
63 static void collect_nodes(std::list<const XFormNode*> *res, const XFormNode *node)
64 {
65 if(!node) return;
67 res->push_back(node);
69 for(int i=0; i<node->get_children_count(); i++) {
70 collect_nodes(res, node->get_child(i));
71 }
72 }
74 bool Scene::save_anim_xml(const XFormNode *node, goat3d_io *io) const
75 {
76 xmlout(io, 0, "<anim>\n");
78 const char *anim_name = node->get_animation_name();
79 if(anim_name && *anim_name) {
80 xmlout(io, 1, "<name string=\"%s\"/>\n", anim_name);
81 }
83 std::list<const XFormNode*> allnodes;
84 collect_nodes(&allnodes, node);
86 std::list<const XFormNode*>::const_iterator it = allnodes.begin();
87 while(it != allnodes.end()) {
88 const XFormNode *n = *it++;
89 write_node_anim(io, n, 1);
90 }
92 xmlout(io, 0, "</anim>\n");
93 return true;
94 }
96 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level)
97 {
98 xmlout(io, level, "<mtl>\n");
99 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str());
101 for(int i=0; i<mat->get_attrib_count(); i++) {
102 xmlout(io, level + 1, "<attr>\n");
103 xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i));
105 const MaterialAttrib &attr = (*mat)[i];
106 xmlout(io, level + 2, "<val float4=\"%g %g %g %g\"/>\n", attr.value.x,
107 attr.value.y, attr.value.z, attr.value.w);
108 if(!attr.map.empty()) {
109 xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str());
110 }
111 xmlout(io, level + 1, "</attr>\n");
112 }
113 xmlout(io, level, "</mtl>\n\n");
114 return true;
115 }
117 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level)
118 {
119 // first write the external (openctm) mesh file
120 const char *prefix = scn->get_name();
121 if(!prefix) {
122 prefix = "goat";
123 }
125 char *mesh_filename = (char*)alloca(strlen(prefix) + 32);
126 sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx);
128 if(!mesh->save(mesh_filename)) {
129 return false;
130 }
132 // then refer to that filename in the XML tags
133 xmlout(io, level, "<mesh>\n");
134 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str());
135 if(mesh->material) {
136 xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
137 }
138 xmlout(io, level + 1, "<file string=\"%s\"/>\n", clean_filename(mesh_filename).c_str());
139 xmlout(io, level, "</mesh>\n\n");
140 return true;
141 }
143 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level)
144 {
145 return true;
146 }
148 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level)
149 {
150 return true;
151 }
153 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level)
154 {
155 xmlout(io, level, "<node>\n");
156 xmlout(io, level + 1, "<name string=\"%s\"/>\n", node->get_name());
158 const XFormNode *parent = node->get_parent();
159 if(parent) {
160 xmlout(io, level + 1, "<parent string=\"%s\"/>\n", parent->get_name());
161 }
163 const char *type = 0;
164 const Object *obj = node->get_object();
165 if(dynamic_cast<const Mesh*>(obj)) {
166 type = "mesh";
167 } else if(dynamic_cast<const Light*>(obj)) {
168 type = "light";
169 } else if(dynamic_cast<const Camera*>(obj)) {
170 type = "camera";
171 }
173 if(type) {
174 xmlout(io, level + 1, "<%s string=\"%s\"/>\n", type, obj->name.c_str());
175 }
177 Vector3 pos = node->get_node_position();
178 Quaternion rot = node->get_node_rotation();
179 Vector3 scale = node->get_node_scaling();
180 Vector3 pivot = node->get_pivot();
182 Matrix4x4 xform;
183 node->get_node_xform(0, &xform);
185 xmlout(io, level + 1, "<pos float3=\"%g %g %g\"/>\n", pos.x, pos.y, pos.z);
186 xmlout(io, level + 1, "<rot float4=\"%g %g %g %g\"/>\n", rot.v.x, rot.v.y, rot.v.z, rot.s);
187 xmlout(io, level + 1, "<scale float3=\"%g %g %g\"/>\n", scale.x, scale.y, scale.z);
188 xmlout(io, level + 1, "<pivot float3=\"%g %g %g\"/>\n", pivot.x, pivot.y, pivot.z);
190 xmlout(io, level + 1, "<matrix0 float4=\"%g %g %g %g\"/>\n", xform[0][0], xform[0][1], xform[0][2], xform[0][3]);
191 xmlout(io, level + 1, "<matrix1 float4=\"%g %g %g %g\"/>\n", xform[1][0], xform[1][1], xform[1][2], xform[1][3]);
192 xmlout(io, level + 1, "<matrix2 float4=\"%g %g %g %g\"/>\n", xform[2][0], xform[2][1], xform[2][2], xform[2][3]);
194 xmlout(io, level, "</node>\n");
195 return true;
196 }
198 static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level)
199 {
200 /* NOTE: the order of names must correspond to the order of the
201 * XFormNode::POSITION_TRACK/ROTATION_TRACK/SCALING_TRACK enum
202 */
203 static const char *attr_names[] = { "position", "rotation", "scaling" };
205 // for each of: position/rotation/scaling
206 for(int i=0; i<3; i++) {
207 int num_keys = node->get_key_count(i);
208 if(!num_keys) continue;
210 xmlout(io, level + 1, "<track>\n");
211 xmlout(io, level + 2, "<node string=\"%s\"/>\n", node->get_name());
212 xmlout(io, level + 2, "<attr string=\"%s\"/>\n\n", attr_names[i]);
214 // for each key in that track
215 for(int j=0; j<num_keys; j++) {
216 long tm = node->get_key_time(i, j);
218 float value[4];
219 int num_elems = node->get_key_value(i, j, value);
221 if(num_elems == 3) {
222 xmlout(io, level + 2, "<key><time int=\"%ld\"/><value float3=\"%g %g %g\"/></key>\n",
223 tm, value[0], value[1], value[2]);
224 } else {
225 xmlout(io, level + 2, "<key><time int=\"%ld\"/><value float4=\"%g %g %g %g\"/></key>\n",
226 tm, value[0], value[1], value[2], value[3]);
227 }
228 }
230 xmlout(io, level + 1, "</track>\n");
231 }
232 return true;
233 }
235 static void xmlout(goat3d_io *io, int level, const char *fmt, ...)
236 {
237 for(int i=0; i<level; i++) {
238 io_fprintf(io, " ");
239 }
241 va_list ap;
242 va_start(ap, fmt);
243 io_vfprintf(io, fmt, ap);
244 va_end(ap);
245 }