goat3d
view src/goat3d_readxml.cc @ 72:36e39632db75
- fixed exporter animation bounds calculation
- fixed missing scene name in exported meshes
- rewritting goatview as a full GUI app with Qt
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 06 May 2014 03:31:35 +0300 |
parents | 6d514398a728 |
children | ab66cdabf6f2 |
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 <stdio.h>
19 #include "goat3d.h"
20 #include "goat3d_impl.h"
21 #include "tinyxml2.h"
22 #include "log.h"
24 using namespace g3dimpl;
25 using namespace tinyxml2;
27 static Material *read_material(Scene *scn, XMLElement *xml_mtl);
28 static const char *read_material_attrib(MaterialAttrib *attr, XMLElement *xml_attr);
29 static Mesh *read_mesh(Scene *scn, XMLElement *xml_mesh);
30 static std::string get_name(XMLElement *node, int idx);
32 bool Scene::loadxml(goat3d_io *io)
33 {
34 long bytes = io->seek(0, SEEK_END, io->cls);
35 io->seek(0, SEEK_SET, io->cls);
37 char *buf = new char[bytes];
38 if(io->read(buf, bytes, io->cls) < bytes) {
39 logmsg(LOG_ERROR, "failed to read XML scene file\n");
40 delete [] buf;
41 return false;
42 }
44 XMLDocument xml;
45 XMLError err = xml.Parse(buf, bytes);
46 if(err) {
47 logmsg(LOG_ERROR, "failed to parse XML scene file: %s\n%s\n", xml.GetErrorStr1(),
48 xml.GetErrorStr2());
49 delete [] buf;
50 return false;
51 }
53 XMLElement *root = xml.RootElement();
54 if(strcmp(root->Name(), "scene") != 0) {
55 logmsg(LOG_ERROR, "invalid XML file, root node is not <scene>\n");
56 delete [] buf;
57 return false;
58 }
60 XMLElement *elem;
62 // get all materials
63 elem = root->FirstChildElement("mtl");
64 while(elem) {
65 Material *mtl = read_material(this, elem);
66 if(mtl) {
67 add_material(mtl);
68 }
69 elem = elem->NextSiblingElement("mtl");
70 }
72 // get all meshes
73 elem = root->FirstChildElement("mesh");
74 while(elem) {
75 Mesh *mesh = read_mesh(this, elem);
76 if(mesh) {
77 add_mesh(mesh);
78 }
79 elem = elem->NextSiblingElement("mesh");
80 }
82 delete [] buf;
83 return true;
84 }
86 bool Scene::load_anim_xml(goat3d_io *io)
87 {
88 long bytes = io->seek(0, SEEK_END, io->cls);
89 io->seek(0, SEEK_SET, io->cls);
91 char *buf = new char[bytes];
92 if(io->read(buf, bytes, io->cls) < bytes) {
93 logmsg(LOG_ERROR, "failed to read XML animation file\n");
94 delete [] buf;
95 return false;
96 }
98 XMLDocument xml;
99 XMLError err = xml.Parse(buf, bytes);
100 if(err) {
101 logmsg(LOG_ERROR, "failed to parse XML animation file: %s\n%s\n", xml.GetErrorStr1(),
102 xml.GetErrorStr2());
103 delete [] buf;
104 return false;
105 }
107 XMLElement *root = xml.RootElement();
108 if(strcmp(root->Name(), "anim") != 0) {
109 logmsg(LOG_ERROR, "invalid XML file, root node is not <anim>\n");
110 delete [] buf;
111 return false;
112 }
114 XMLElement *elem;
116 elem = root->FirstChildElement();
117 while(elem) {
118 const char *elem_name = elem->Name();
120 if(strcmp(elem_name, "name") == 0) {
121 } else if(strcmp(elem_name, "attr") == 0) {
122 }
123 elem = elem->NextSiblingElement();
124 }
126 delete [] buf;
127 return true;
128 }
130 static Material *read_material(Scene *scn, XMLElement *xml_mtl)
131 {
132 Material *mtl = new Material;
133 mtl->name = get_name(xml_mtl, scn->get_material_count());
135 // get all the material attributes in turn
136 XMLElement *elem = xml_mtl->FirstChildElement("attr");
137 while(elem) {
138 MaterialAttrib attr;
139 const char *name = read_material_attrib(&attr, elem);
140 if(name) {
141 (*mtl)[name] = attr;
142 }
144 elem = elem->NextSiblingElement("attr");
145 }
147 return mtl;
148 }
150 static const char *read_material_attrib(MaterialAttrib *attr, XMLElement *xml_attr)
151 {
152 const char *name;
154 XMLElement *elem;
155 if((elem = xml_attr->FirstChildElement("name"))) {
156 if(!(name = elem->Attribute("string"))) {
157 return 0;
158 }
159 }
161 if((elem = xml_attr->FirstChildElement("val"))) {
162 if(elem->QueryFloatAttribute("float", &attr->value.x) != XML_NO_ERROR) {
163 // try a float3
164 const char *valstr = elem->Attribute("float3");
165 if(!valstr || sscanf(valstr, "%f %f %f", &attr->value.x, &attr->value.y,
166 &attr->value.z) != 3) {
167 // try a float4
168 valstr = elem->Attribute("float4");
169 if(!valstr || sscanf(valstr, "%f %f %f %f", &attr->value.x, &attr->value.y,
170 &attr->value.z, &attr->value.w) != 4) {
171 // no valid val attribute found
172 return 0;
173 }
174 }
175 }
176 }
178 if((elem = xml_attr->FirstChildElement("map"))) {
179 const char *tex = elem->Attribute("string");
180 if(tex) {
181 attr->map = std::string(tex);
182 }
183 }
185 return name;
186 }
188 static Mesh *read_mesh(Scene *scn, XMLElement *xml_mesh)
189 {
190 Mesh *mesh = new Mesh;
191 mesh->name = get_name(xml_mesh, scn->get_mesh_count());
193 XMLElement *elem;
194 if((elem = xml_mesh->FirstChildElement("material"))) {
195 int idx;
196 if(elem->QueryIntAttribute("int", &idx) == XML_NO_ERROR) {
197 mesh->material = scn->get_material(idx);
198 } else {
199 // try string
200 const char *mtlstr = elem->Attribute("string");
201 if(mtlstr) {
202 mesh->material = scn->get_material(mtlstr);
203 }
204 }
205 }
207 /* reading mesh data from XML is not supported, only MESH_FILE can be used to
208 * specify an external mesh file to be loaded
209 */
211 if((elem = xml_mesh->FirstChildElement("file"))) {
212 const char *fname = elem->Attribute("string");
213 if(fname) {
214 if(!mesh->load(fname)) {
215 delete mesh;
216 return 0;
217 }
218 }
219 }
221 return mesh;
222 }
224 static std::string get_name(XMLElement *node, int idx)
225 {
226 char buf[64];
227 const char *name = 0;
229 XMLElement *elem;
230 if((elem = node->FirstChildElement("name"))) {
231 name = elem->Attribute("string");
232 }
234 if(!name) {
235 sprintf(buf, "mesh%04d", idx);
236 name = buf;
237 }
239 return std::string(name);
240 }