goat3d

annotate src/goat3d_readxml.cc @ 52:cb5414f406eb

merged
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 17 Jan 2014 18:27:47 +0200
parents fa5c52ea9d59 0be413ac2e0a
children 6d514398a728
rev   line source
nuclear@19 1 #include <stdio.h>
nuclear@19 2 #include "goat3d.h"
nuclear@19 3 #include "goat3d_impl.h"
nuclear@19 4 #include "tinyxml2.h"
nuclear@19 5 #include "log.h"
nuclear@19 6
nuclear@47 7 using namespace g3dimpl;
nuclear@19 8 using namespace tinyxml2;
nuclear@19 9
nuclear@19 10 static Material *read_material(Scene *scn, XMLElement *xml_mtl);
nuclear@19 11 static const char *read_material_attrib(MaterialAttrib *attr, XMLElement *xml_attr);
nuclear@19 12 static Mesh *read_mesh(Scene *scn, XMLElement *xml_mesh);
nuclear@19 13 static std::string get_name(XMLElement *node, int idx);
nuclear@19 14
nuclear@19 15 bool Scene::loadxml(goat3d_io *io)
nuclear@19 16 {
nuclear@19 17 long bytes = io->seek(0, SEEK_END, io->cls);
nuclear@19 18 io->seek(0, SEEK_SET, io->cls);
nuclear@19 19
nuclear@19 20 char *buf = new char[bytes];
nuclear@19 21 if(io->read(buf, bytes, io->cls) < bytes) {
nuclear@19 22 logmsg(LOG_ERROR, "failed to read XML scene file\n");
nuclear@45 23 delete [] buf;
nuclear@19 24 return false;
nuclear@19 25 }
nuclear@19 26
nuclear@19 27 XMLDocument xml;
nuclear@19 28 XMLError err = xml.Parse(buf, bytes);
nuclear@19 29 if(err) {
nuclear@19 30 logmsg(LOG_ERROR, "failed to parse XML scene file: %s\n%s\n", xml.GetErrorStr1(),
nuclear@19 31 xml.GetErrorStr2());
nuclear@45 32 delete [] buf;
nuclear@19 33 return false;
nuclear@19 34 }
nuclear@19 35
nuclear@19 36 XMLElement *root = xml.RootElement();
nuclear@19 37 if(strcmp(root->Name(), "scene") != 0) {
nuclear@19 38 logmsg(LOG_ERROR, "invalid XML file, root node is not <scene>\n");
nuclear@45 39 delete [] buf;
nuclear@19 40 return false;
nuclear@19 41 }
nuclear@19 42
nuclear@19 43 XMLElement *elem;
nuclear@19 44
nuclear@19 45 // get all materials
nuclear@19 46 elem = root->FirstChildElement("mtl");
nuclear@19 47 while(elem) {
nuclear@19 48 Material *mtl = read_material(this, elem);
nuclear@19 49 if(mtl) {
nuclear@19 50 add_material(mtl);
nuclear@19 51 }
nuclear@19 52 elem = elem->NextSiblingElement("mtl");
nuclear@19 53 }
nuclear@19 54
nuclear@19 55 // get all meshes
nuclear@19 56 elem = root->FirstChildElement("mesh");
nuclear@19 57 while(elem) {
nuclear@19 58 Mesh *mesh = read_mesh(this, elem);
nuclear@19 59 if(mesh) {
nuclear@19 60 add_mesh(mesh);
nuclear@19 61 }
nuclear@19 62 elem = elem->NextSiblingElement("mesh");
nuclear@19 63 }
nuclear@19 64
nuclear@45 65 delete [] buf;
nuclear@45 66 return true;
nuclear@19 67 }
nuclear@19 68
nuclear@51 69 bool Scene::load_anim_xml(goat3d_io *io)
nuclear@51 70 {
nuclear@51 71 long bytes = io->seek(0, SEEK_END, io->cls);
nuclear@51 72 io->seek(0, SEEK_SET, io->cls);
nuclear@51 73
nuclear@51 74 char *buf = new char[bytes];
nuclear@51 75 if(io->read(buf, bytes, io->cls) < bytes) {
nuclear@51 76 logmsg(LOG_ERROR, "failed to read XML animation file\n");
nuclear@51 77 delete [] buf;
nuclear@51 78 return false;
nuclear@51 79 }
nuclear@51 80
nuclear@51 81 XMLDocument xml;
nuclear@51 82 XMLError err = xml.Parse(buf, bytes);
nuclear@51 83 if(err) {
nuclear@51 84 logmsg(LOG_ERROR, "failed to parse XML animation file: %s\n%s\n", xml.GetErrorStr1(),
nuclear@51 85 xml.GetErrorStr2());
nuclear@51 86 delete [] buf;
nuclear@51 87 return false;
nuclear@51 88 }
nuclear@51 89
nuclear@51 90 XMLElement *root = xml.RootElement();
nuclear@51 91 if(strcmp(root->Name(), "anim") != 0) {
nuclear@51 92 logmsg(LOG_ERROR, "invalid XML file, root node is not <anim>\n");
nuclear@51 93 delete [] buf;
nuclear@51 94 return false;
nuclear@51 95 }
nuclear@51 96
nuclear@51 97 XMLElement *elem;
nuclear@51 98
nuclear@51 99 elem = root->FirstChildElement();
nuclear@51 100 while(elem) {
nuclear@51 101 const char *elem_name = elem->Name();
nuclear@51 102
nuclear@51 103 if(strcmp(elem_name, "name") == 0) {
nuclear@51 104 } else if(strcmp(elem_name, "attr") == 0) {
nuclear@51 105 }
nuclear@51 106 elem = elem->NextSiblingElement();
nuclear@51 107 }
nuclear@51 108
nuclear@51 109 delete [] buf;
nuclear@51 110 return true;
nuclear@51 111 }
nuclear@19 112
nuclear@50 113 bool Scene::load_anim_xml(goat3d_io *io)
nuclear@50 114 {
nuclear@50 115 return false;
nuclear@50 116 }
nuclear@50 117
nuclear@50 118
nuclear@19 119 static Material *read_material(Scene *scn, XMLElement *xml_mtl)
nuclear@19 120 {
nuclear@19 121 Material *mtl = new Material;
nuclear@19 122 mtl->name = get_name(xml_mtl, scn->get_material_count());
nuclear@19 123
nuclear@19 124 // get all the material attributes in turn
nuclear@19 125 XMLElement *elem = xml_mtl->FirstChildElement("attr");
nuclear@19 126 while(elem) {
nuclear@19 127 MaterialAttrib attr;
nuclear@19 128 const char *name = read_material_attrib(&attr, elem);
nuclear@19 129 if(name) {
nuclear@19 130 (*mtl)[name] = attr;
nuclear@19 131 }
nuclear@19 132
nuclear@19 133 elem = elem->NextSiblingElement("attr");
nuclear@19 134 }
nuclear@19 135
nuclear@19 136 return mtl;
nuclear@19 137 }
nuclear@19 138
nuclear@19 139 static const char *read_material_attrib(MaterialAttrib *attr, XMLElement *xml_attr)
nuclear@19 140 {
nuclear@19 141 const char *name;
nuclear@19 142
nuclear@19 143 XMLElement *elem;
nuclear@19 144 if((elem = xml_attr->FirstChildElement("name"))) {
nuclear@19 145 if(!(name = elem->Attribute("string"))) {
nuclear@19 146 return 0;
nuclear@19 147 }
nuclear@19 148 }
nuclear@19 149
nuclear@19 150 if((elem = xml_attr->FirstChildElement("val"))) {
nuclear@19 151 if(elem->QueryFloatAttribute("float", &attr->value.x) != XML_NO_ERROR) {
nuclear@19 152 // try a float3
nuclear@19 153 const char *valstr = elem->Attribute("float3");
nuclear@19 154 if(!valstr || sscanf(valstr, "%f %f %f", &attr->value.x, &attr->value.y,
nuclear@19 155 &attr->value.z) != 3) {
nuclear@19 156 // try a float4
nuclear@19 157 valstr = elem->Attribute("float4");
nuclear@19 158 if(!valstr || sscanf(valstr, "%f %f %f %f", &attr->value.x, &attr->value.y,
nuclear@19 159 &attr->value.z, &attr->value.w) != 4) {
nuclear@19 160 // no valid val attribute found
nuclear@19 161 return 0;
nuclear@19 162 }
nuclear@19 163 }
nuclear@19 164 }
nuclear@19 165 }
nuclear@19 166
nuclear@19 167 if((elem = xml_attr->FirstChildElement("map"))) {
nuclear@19 168 const char *tex = elem->Attribute("string");
nuclear@19 169 if(tex) {
nuclear@19 170 attr->map = std::string(tex);
nuclear@19 171 }
nuclear@19 172 }
nuclear@19 173
nuclear@19 174 return name;
nuclear@19 175 }
nuclear@19 176
nuclear@19 177 static Mesh *read_mesh(Scene *scn, XMLElement *xml_mesh)
nuclear@19 178 {
nuclear@19 179 Mesh *mesh = new Mesh;
nuclear@19 180 mesh->name = get_name(xml_mesh, scn->get_mesh_count());
nuclear@19 181
nuclear@19 182 XMLElement *elem;
nuclear@19 183 if((elem = xml_mesh->FirstChildElement("material"))) {
nuclear@19 184 int idx;
nuclear@19 185 if(elem->QueryIntAttribute("int", &idx) == XML_NO_ERROR) {
nuclear@19 186 mesh->material = scn->get_material(idx);
nuclear@19 187 } else {
nuclear@19 188 // try string
nuclear@19 189 const char *mtlstr = elem->Attribute("string");
nuclear@19 190 if(mtlstr) {
nuclear@19 191 mesh->material = scn->get_material(mtlstr);
nuclear@19 192 }
nuclear@19 193 }
nuclear@19 194 }
nuclear@19 195
nuclear@19 196 /* reading mesh data from XML is not supported, only MESH_FILE can be used to
nuclear@19 197 * specify an external mesh file to be loaded
nuclear@19 198 */
nuclear@19 199
nuclear@19 200 if((elem = xml_mesh->FirstChildElement("file"))) {
nuclear@19 201 const char *fname = elem->Attribute("string");
nuclear@19 202 if(fname) {
nuclear@19 203 if(!mesh->load(fname)) {
nuclear@19 204 delete mesh;
nuclear@19 205 return 0;
nuclear@19 206 }
nuclear@19 207 }
nuclear@19 208 }
nuclear@19 209
nuclear@19 210 return mesh;
nuclear@19 211 }
nuclear@19 212
nuclear@19 213 static std::string get_name(XMLElement *node, int idx)
nuclear@19 214 {
nuclear@19 215 char buf[64];
nuclear@19 216 const char *name = 0;
nuclear@19 217
nuclear@19 218 XMLElement *elem;
nuclear@19 219 if((elem = node->FirstChildElement("name"))) {
nuclear@19 220 name = elem->Attribute("string");
nuclear@19 221 }
nuclear@19 222
nuclear@19 223 if(!name) {
nuclear@19 224 sprintf(buf, "mesh%04d", idx);
nuclear@19 225 name = buf;
nuclear@19 226 }
nuclear@19 227
nuclear@19 228 return std::string(name);
nuclear@19 229 }