goat3d

annotate 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
rev   line source
nuclear@47 1 #include <list>
nuclear@14 2 #include <stdarg.h>
nuclear@14 3 #include "goat3d_impl.h"
nuclear@47 4 #include "anim/anim.h"
nuclear@17 5 #include "log.h"
nuclear@14 6
nuclear@47 7 using namespace g3dimpl;
nuclear@47 8
nuclear@14 9 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
nuclear@14 10 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level);
nuclear@14 11 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level);
nuclear@14 12 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level);
nuclear@14 13 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level);
nuclear@47 14 static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level);
nuclear@14 15 static void xmlout(goat3d_io *io, int level, const char *fmt, ...);
nuclear@14 16
nuclear@14 17 bool Scene::savexml(goat3d_io *io) const
nuclear@14 18 {
nuclear@14 19 xmlout(io, 0, "<scene>\n");
nuclear@14 20
nuclear@14 21 // write environment stuff
nuclear@14 22 xmlout(io, 1, "<env>\n");
nuclear@18 23 xmlout(io, 2, "<ambient float3=\"%g %g %g\"/>\n", ambient.x, ambient.y, ambient.z);
nuclear@18 24 xmlout(io, 1, "</env>\n\n");
nuclear@14 25
nuclear@14 26 for(size_t i=0; i<materials.size(); i++) {
nuclear@14 27 write_material(this, io, materials[i], 1);
nuclear@14 28 }
nuclear@14 29 for(size_t i=0; i<meshes.size(); i++) {
nuclear@58 30 write_mesh(this, io, meshes[i], (int)i, 1);
nuclear@14 31 }
nuclear@14 32 for(size_t i=0; i<lights.size(); i++) {
nuclear@14 33 write_light(this, io, lights[i], 1);
nuclear@14 34 }
nuclear@14 35 for(size_t i=0; i<cameras.size(); i++) {
nuclear@14 36 write_camera(this, io, cameras[i], 1);
nuclear@14 37 }
nuclear@14 38 for(size_t i=0; i<nodes.size(); i++) {
nuclear@14 39 write_node(this, io, nodes[i], 1);
nuclear@14 40 }
nuclear@14 41
nuclear@14 42 xmlout(io, 0, "</scene>\n");
nuclear@14 43 return true;
nuclear@14 44 }
nuclear@14 45
nuclear@55 46 bool Scene::save_anim_xml(goat3d_io *io) const
nuclear@47 47 {
nuclear@47 48 xmlout(io, 0, "<anim>\n");
nuclear@47 49
nuclear@55 50 if(!nodes.empty()) {
nuclear@55 51 const char *anim_name = nodes[0]->get_animation_name();
nuclear@55 52 if(anim_name && *anim_name) {
nuclear@55 53 xmlout(io, 1, "<name string=\"%s\"/>\n", anim_name);
nuclear@55 54 }
nuclear@47 55 }
nuclear@47 56
nuclear@55 57 for(size_t i=0; i<nodes.size(); i++) {
nuclear@55 58 write_node_anim(io, nodes[i], 1);
nuclear@47 59 }
nuclear@47 60
nuclear@47 61 xmlout(io, 0, "</anim>\n");
nuclear@47 62 return true;
nuclear@47 63 }
nuclear@47 64
nuclear@14 65 static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level)
nuclear@14 66 {
nuclear@14 67 xmlout(io, level, "<mtl>\n");
nuclear@14 68 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str());
nuclear@14 69
nuclear@14 70 for(int i=0; i<mat->get_attrib_count(); i++) {
nuclear@14 71 xmlout(io, level + 1, "<attr>\n");
nuclear@14 72 xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i));
nuclear@14 73
nuclear@14 74 const MaterialAttrib &attr = (*mat)[i];
nuclear@18 75 xmlout(io, level + 2, "<val float4=\"%g %g %g %g\"/>\n", attr.value.x,
nuclear@14 76 attr.value.y, attr.value.z, attr.value.w);
nuclear@14 77 if(!attr.map.empty()) {
nuclear@14 78 xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str());
nuclear@14 79 }
nuclear@14 80 xmlout(io, level + 1, "</attr>\n");
nuclear@14 81 }
nuclear@18 82 xmlout(io, level, "</mtl>\n\n");
nuclear@14 83 return true;
nuclear@14 84 }
nuclear@14 85
nuclear@14 86 static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level)
nuclear@14 87 {
nuclear@14 88 // first write the external (openctm) mesh file
nuclear@14 89 const char *prefix = scn->get_name();
nuclear@14 90 if(!prefix) {
nuclear@14 91 prefix = "goat";
nuclear@14 92 }
nuclear@14 93
nuclear@14 94 char *mesh_filename = (char*)alloca(strlen(prefix) + 32);
nuclear@14 95 sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx);
nuclear@14 96
nuclear@19 97 if(!mesh->save(mesh_filename)) {
nuclear@19 98 return false;
nuclear@19 99 }
nuclear@14 100
nuclear@14 101 // then refer to that filename in the XML tags
nuclear@14 102 xmlout(io, level, "<mesh>\n");
nuclear@14 103 xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str());
nuclear@17 104 if(mesh->material) {
nuclear@17 105 xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
nuclear@17 106 }
nuclear@51 107 xmlout(io, level + 1, "<file string=\"%s\"/>\n", clean_filename(mesh_filename).c_str());
nuclear@18 108 xmlout(io, level, "</mesh>\n\n");
nuclear@14 109 return true;
nuclear@14 110 }
nuclear@14 111
nuclear@14 112 static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level)
nuclear@14 113 {
nuclear@14 114 return true;
nuclear@14 115 }
nuclear@14 116
nuclear@14 117 static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level)
nuclear@14 118 {
nuclear@14 119 return true;
nuclear@14 120 }
nuclear@14 121
nuclear@14 122 static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level)
nuclear@14 123 {
nuclear@30 124 xmlout(io, level, "<node>\n");
nuclear@30 125 xmlout(io, level + 1, "<name string=\"%s\"/>\n", node->get_name());
nuclear@30 126
nuclear@47 127 const XFormNode *parent = node->get_parent();
nuclear@30 128 if(parent) {
nuclear@30 129 xmlout(io, level + 1, "<parent string=\"%s\"/>\n", parent->get_name());
nuclear@30 130 }
nuclear@30 131
nuclear@30 132 const char *type = 0;
nuclear@30 133 const Object *obj = node->get_object();
nuclear@30 134 if(dynamic_cast<const Mesh*>(obj)) {
nuclear@30 135 type = "mesh";
nuclear@30 136 } else if(dynamic_cast<const Light*>(obj)) {
nuclear@30 137 type = "light";
nuclear@30 138 } else if(dynamic_cast<const Camera*>(obj)) {
nuclear@30 139 type = "camera";
nuclear@30 140 }
nuclear@30 141
nuclear@30 142 if(type) {
nuclear@30 143 xmlout(io, level + 1, "<%s string=\"%s\"/>\n", type, obj->name.c_str());
nuclear@30 144 }
nuclear@30 145
nuclear@30 146 Vector3 pos = node->get_node_position();
nuclear@30 147 Quaternion rot = node->get_node_rotation();
nuclear@30 148 Vector3 scale = node->get_node_scaling();
nuclear@30 149 Vector3 pivot = node->get_pivot();
nuclear@30 150
nuclear@30 151 Matrix4x4 xform;
nuclear@30 152 node->get_node_xform(0, &xform);
nuclear@30 153
nuclear@30 154 xmlout(io, level + 1, "<pos float3=\"%g %g %g\"/>\n", pos.x, pos.y, pos.z);
nuclear@30 155 xmlout(io, level + 1, "<rot float4=\"%g %g %g %g\"/>\n", rot.v.x, rot.v.y, rot.v.z, rot.s);
nuclear@30 156 xmlout(io, level + 1, "<scale float3=\"%g %g %g\"/>\n", scale.x, scale.y, scale.z);
nuclear@30 157 xmlout(io, level + 1, "<pivot float3=\"%g %g %g\"/>\n", pivot.x, pivot.y, pivot.z);
nuclear@30 158
nuclear@30 159 xmlout(io, level + 1, "<matrix0 float4=\"%g %g %g %g\"/>\n", xform[0][0], xform[0][1], xform[0][2], xform[0][3]);
nuclear@30 160 xmlout(io, level + 1, "<matrix1 float4=\"%g %g %g %g\"/>\n", xform[1][0], xform[1][1], xform[1][2], xform[1][3]);
nuclear@30 161 xmlout(io, level + 1, "<matrix2 float4=\"%g %g %g %g\"/>\n", xform[2][0], xform[2][1], xform[2][2], xform[2][3]);
nuclear@30 162
nuclear@30 163 xmlout(io, level, "</node>\n");
nuclear@14 164 return true;
nuclear@14 165 }
nuclear@14 166
nuclear@47 167 static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level)
nuclear@47 168 {
nuclear@51 169 /* NOTE: the order of names must correspond to the order of the
nuclear@48 170 * XFormNode::POSITION_TRACK/ROTATION_TRACK/SCALING_TRACK enum
nuclear@48 171 */
nuclear@47 172 static const char *attr_names[] = { "position", "rotation", "scaling" };
nuclear@47 173
nuclear@48 174 // for each of: position/rotation/scaling
nuclear@48 175 for(int i=0; i<3; i++) {
nuclear@48 176 int num_keys = node->get_key_count(i);
nuclear@48 177 if(!num_keys) continue;
nuclear@47 178
nuclear@47 179 xmlout(io, level + 1, "<track>\n");
nuclear@47 180 xmlout(io, level + 2, "<node string=\"%s\"/>\n", node->get_name());
nuclear@48 181 xmlout(io, level + 2, "<attr string=\"%s\"/>\n\n", attr_names[i]);
nuclear@47 182
nuclear@48 183 // for each key in that track
nuclear@48 184 for(int j=0; j<num_keys; j++) {
nuclear@48 185 long tm = node->get_key_time(i, j);
nuclear@48 186
nuclear@48 187 float value[4];
nuclear@48 188 int num_elems = node->get_key_value(i, j, value);
nuclear@48 189
nuclear@48 190 if(num_elems == 3) {
nuclear@48 191 xmlout(io, level + 2, "<key><time int=\"%ld\"/><value float3=\"%g %g %g\"/></key>\n",
nuclear@48 192 tm, value[0], value[1], value[2]);
nuclear@48 193 } else {
nuclear@48 194 xmlout(io, level + 2, "<key><time int=\"%ld\"/><value float4=\"%g %g %g %g\"/></key>\n",
nuclear@48 195 tm, value[0], value[1], value[2], value[3]);
nuclear@48 196 }
nuclear@48 197 }
nuclear@47 198
nuclear@47 199 xmlout(io, level + 1, "</track>\n");
nuclear@47 200 }
nuclear@47 201 return true;
nuclear@47 202 }
nuclear@14 203
nuclear@14 204 static void xmlout(goat3d_io *io, int level, const char *fmt, ...)
nuclear@14 205 {
nuclear@14 206 for(int i=0; i<level; i++) {
nuclear@14 207 io_fprintf(io, " ");
nuclear@14 208 }
nuclear@14 209
nuclear@14 210 va_list ap;
nuclear@14 211 va_start(ap, fmt);
nuclear@14 212 io_vfprintf(io, fmt, ap);
nuclear@14 213 va_end(ap);
nuclear@14 214 }