goat3d

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