goat3d
view src/goat3d_writexml.cc @ 58:d317eb4f83da
- made everything compile properly on windows again
- removed libanim/libvmath, we'll use them as external dependencies
- added new maxgoat_stub 3dsmax plugin project. Gets loaded as a max plugin and
loads the actual maxgoat (and later maxgoat_anim) exporters on demand, to
allow reloading the actual exporters without having to restart 3dsmax (which
takes AGES).
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 25 Mar 2014 03:19:55 +0200 |
parents | af1310ed212b |
children | 99715321ad6d |
line source
1 #include <list>
2 #include <stdarg.h>
3 #include "goat3d_impl.h"
4 #include "anim/anim.h"
5 #include "log.h"
7 using namespace g3dimpl;
9 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
10 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level);
11 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level);
12 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level);
13 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level);
14 static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level);
15 static void xmlout(goat3d_io *io, int level, const char *fmt, ...);
17 bool Scene::savexml(goat3d_io *io) const
18 {
19 xmlout(io, 0, "<scene>\n");
21 // write environment stuff
22 xmlout(io, 1, "<env>\n");
23 xmlout(io, 2, "<ambient float3=\"%g %g %g\"/>\n", ambient.x, ambient.y, ambient.z);
24 xmlout(io, 1, "</env>\n\n");
26 for(size_t i=0; i<materials.size(); i++) {
27 write_material(this, io, materials[i], 1);
28 }
29 for(size_t i=0; i<meshes.size(); i++) {
30 write_mesh(this, io, meshes[i], (int)i, 1);
31 }
32 for(size_t i=0; i<lights.size(); i++) {
33 write_light(this, io, lights[i], 1);
34 }
35 for(size_t i=0; i<cameras.size(); i++) {
36 write_camera(this, io, cameras[i], 1);
37 }
38 for(size_t i=0; i<nodes.size(); i++) {
39 write_node(this, io, nodes[i], 1);
40 }
42 xmlout(io, 0, "</scene>\n");
43 return true;
44 }
46 bool Scene::save_anim_xml(goat3d_io *io) const
47 {
48 xmlout(io, 0, "<anim>\n");
50 if(!nodes.empty()) {
51 const char *anim_name = nodes[0]->get_animation_name();
52 if(anim_name && *anim_name) {
53 xmlout(io, 1, "<name string=\"%s\"/>\n", anim_name);
54 }
55 }
57 for(size_t i=0; i<nodes.size(); i++) {
58 write_node_anim(io, nodes[i], 1);
59 }
61 xmlout(io, 0, "</anim>\n");
62 return true;
63 }
65 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level)
66 {
67 xmlout(io, level, "<mtl>\n");
68 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str());
70 for(int i=0; i<mat->get_attrib_count(); i++) {
71 xmlout(io, level + 1, "<attr>\n");
72 xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i));
74 const MaterialAttrib &attr = (*mat)[i];
75 xmlout(io, level + 2, "<val float4=\"%g %g %g %g\"/>\n", attr.value.x,
76 attr.value.y, attr.value.z, attr.value.w);
77 if(!attr.map.empty()) {
78 xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str());
79 }
80 xmlout(io, level + 1, "</attr>\n");
81 }
82 xmlout(io, level, "</mtl>\n\n");
83 return true;
84 }
86 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level)
87 {
88 // first write the external (openctm) mesh file
89 const char *prefix = scn->get_name();
90 if(!prefix) {
91 prefix = "goat";
92 }
94 char *mesh_filename = (char*)alloca(strlen(prefix) + 32);
95 sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx);
97 if(!mesh->save(mesh_filename)) {
98 return false;
99 }
101 // then refer to that filename in the XML tags
102 xmlout(io, level, "<mesh>\n");
103 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str());
104 if(mesh->material) {
105 xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
106 }
107 xmlout(io, level + 1, "<file string=\"%s\"/>\n", clean_filename(mesh_filename).c_str());
108 xmlout(io, level, "</mesh>\n\n");
109 return true;
110 }
112 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level)
113 {
114 return true;
115 }
117 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level)
118 {
119 return true;
120 }
122 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level)
123 {
124 xmlout(io, level, "<node>\n");
125 xmlout(io, level + 1, "<name string=\"%s\"/>\n", node->get_name());
127 const XFormNode *parent = node->get_parent();
128 if(parent) {
129 xmlout(io, level + 1, "<parent string=\"%s\"/>\n", parent->get_name());
130 }
132 const char *type = 0;
133 const Object *obj = node->get_object();
134 if(dynamic_cast<const Mesh*>(obj)) {
135 type = "mesh";
136 } else if(dynamic_cast<const Light*>(obj)) {
137 type = "light";
138 } else if(dynamic_cast<const Camera*>(obj)) {
139 type = "camera";
140 }
142 if(type) {
143 xmlout(io, level + 1, "<%s string=\"%s\"/>\n", type, obj->name.c_str());
144 }
146 Vector3 pos = node->get_node_position();
147 Quaternion rot = node->get_node_rotation();
148 Vector3 scale = node->get_node_scaling();
149 Vector3 pivot = node->get_pivot();
151 Matrix4x4 xform;
152 node->get_node_xform(0, &xform);
154 xmlout(io, level + 1, "<pos float3=\"%g %g %g\"/>\n", pos.x, pos.y, pos.z);
155 xmlout(io, level + 1, "<rot float4=\"%g %g %g %g\"/>\n", rot.v.x, rot.v.y, rot.v.z, rot.s);
156 xmlout(io, level + 1, "<scale float3=\"%g %g %g\"/>\n", scale.x, scale.y, scale.z);
157 xmlout(io, level + 1, "<pivot float3=\"%g %g %g\"/>\n", pivot.x, pivot.y, pivot.z);
159 xmlout(io, level + 1, "<matrix0 float4=\"%g %g %g %g\"/>\n", xform[0][0], xform[0][1], xform[0][2], xform[0][3]);
160 xmlout(io, level + 1, "<matrix1 float4=\"%g %g %g %g\"/>\n", xform[1][0], xform[1][1], xform[1][2], xform[1][3]);
161 xmlout(io, level + 1, "<matrix2 float4=\"%g %g %g %g\"/>\n", xform[2][0], xform[2][1], xform[2][2], xform[2][3]);
163 xmlout(io, level, "</node>\n");
164 return true;
165 }
167 static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level)
168 {
169 /* NOTE: the order of names must correspond to the order of the
170 * XFormNode::POSITION_TRACK/ROTATION_TRACK/SCALING_TRACK enum
171 */
172 static const char *attr_names[] = { "position", "rotation", "scaling" };
174 // for each of: position/rotation/scaling
175 for(int i=0; i<3; i++) {
176 int num_keys = node->get_key_count(i);
177 if(!num_keys) continue;
179 xmlout(io, level + 1, "<track>\n");
180 xmlout(io, level + 2, "<node string=\"%s\"/>\n", node->get_name());
181 xmlout(io, level + 2, "<attr string=\"%s\"/>\n\n", attr_names[i]);
183 // for each key in that track
184 for(int j=0; j<num_keys; j++) {
185 long tm = node->get_key_time(i, j);
187 float value[4];
188 int num_elems = node->get_key_value(i, j, value);
190 if(num_elems == 3) {
191 xmlout(io, level + 2, "<key><time int=\"%ld\"/><value float3=\"%g %g %g\"/></key>\n",
192 tm, value[0], value[1], value[2]);
193 } else {
194 xmlout(io, level + 2, "<key><time int=\"%ld\"/><value float4=\"%g %g %g %g\"/></key>\n",
195 tm, value[0], value[1], value[2], value[3]);
196 }
197 }
199 xmlout(io, level + 1, "</track>\n");
200 }
201 return true;
202 }
204 static void xmlout(goat3d_io *io, int level, const char *fmt, ...)
205 {
206 for(int i=0; i<level; i++) {
207 io_fprintf(io, " ");
208 }
210 va_list ap;
211 va_start(ap, fmt);
212 io_vfprintf(io, fmt, ap);
213 va_end(ap);
214 }