goat3d
diff src/goat3d_readxml.cc @ 75:76dea247f75c
in progress
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 08 May 2014 00:50:16 +0300 |
parents | ab66cdabf6f2 |
children | 57e745dd13c2 |
line diff
1.1 --- a/src/goat3d_readxml.cc Tue May 06 13:26:52 2014 +0300 1.2 +++ b/src/goat3d_readxml.cc Thu May 08 00:50:16 2014 +0300 1.3 @@ -16,6 +16,8 @@ 1.4 along with this program. If not, see <http://www.gnu.org/licenses/>. 1.5 */ 1.6 #include <stdio.h> 1.7 +#include <map> 1.8 +#include <string> 1.9 #include "goat3d.h" 1.10 #include "goat3d_impl.h" 1.11 #include "tinyxml2.h" 1.12 @@ -27,7 +29,8 @@ 1.13 static Material *read_material(Scene *scn, XMLElement *xml_mtl); 1.14 static const char *read_material_attrib(MaterialAttrib *attr, XMLElement *xml_attr); 1.15 static Mesh *read_mesh(Scene *scn, XMLElement *xml_mesh); 1.16 -static std::string get_name(XMLElement *node, int idx); 1.17 +static Node *read_node(Scene *scn, XMLElement *xml_node, std::map<Node*, std::string> &linkmap); 1.18 +static std::string get_name(XMLElement *node, int idx, const char *def_prefix); 1.19 1.20 bool Scene::loadxml(goat3d_io *io) 1.21 { 1.22 @@ -79,6 +82,29 @@ 1.23 elem = elem->NextSiblingElement("mesh"); 1.24 } 1.25 1.26 + // get all nodes 1.27 + std::map<Node*, std::string> linkmap; 1.28 + 1.29 + elem = root->FirstChildElement("node"); 1.30 + while(elem) { 1.31 + Node *node = read_node(this, elem, linkmap); 1.32 + if(node) { 1.33 + add_node(node); 1.34 + } 1.35 + elem = elem->NextSiblingElement("node"); 1.36 + } 1.37 + 1.38 + // link up all the nodes in the hierarchy 1.39 + for(size_t i=0; i<nodes.size(); i++) { 1.40 + std::string parent_name = linkmap[nodes[i]]; 1.41 + if(!parent_name.empty()) { 1.42 + Node *parent = get_node(parent_name.c_str()); 1.43 + if(parent) { 1.44 + parent->add_child(nodes[i]); 1.45 + } 1.46 + } 1.47 + } 1.48 + 1.49 delete [] buf; 1.50 return true; 1.51 } 1.52 @@ -130,7 +156,7 @@ 1.53 static Material *read_material(Scene *scn, XMLElement *xml_mtl) 1.54 { 1.55 Material *mtl = new Material; 1.56 - mtl->name = get_name(xml_mtl, scn->get_material_count()); 1.57 + mtl->name = get_name(xml_mtl, scn->get_material_count(), "material"); 1.58 1.59 // get all the material attributes in turn 1.60 XMLElement *elem = xml_mtl->FirstChildElement("attr"); 1.61 @@ -188,7 +214,7 @@ 1.62 static Mesh *read_mesh(Scene *scn, XMLElement *xml_mesh) 1.63 { 1.64 Mesh *mesh = new Mesh; 1.65 - mesh->name = get_name(xml_mesh, scn->get_mesh_count()); 1.66 + mesh->name = get_name(xml_mesh, scn->get_mesh_count(), "mesh"); 1.67 1.68 XMLElement *elem; 1.69 if((elem = xml_mesh->FirstChildElement("material"))) { 1.70 @@ -226,7 +252,74 @@ 1.71 return mesh; 1.72 } 1.73 1.74 -static std::string get_name(XMLElement *node, int idx) 1.75 +static Node *read_node(Scene *scn, XMLElement *xml_node, std::map<Node*, std::string> &linkmap) 1.76 +{ 1.77 + Node *node = new Node; 1.78 + node->set_name(get_name(xml_node, scn->get_node_count(), "node").c_str()); 1.79 + 1.80 + XMLElement *elem; 1.81 + if((elem = xml_node->FirstChildElement("parent"))) { 1.82 + const char *pname = elem->Attribute("string"); 1.83 + if(pname) { 1.84 + linkmap[node] = pname; 1.85 + } 1.86 + } 1.87 + 1.88 + if((elem = xml_node->FirstChildElement("mesh"))) { 1.89 + Mesh *mesh = scn->get_mesh(elem->Attribute("string")); 1.90 + if(mesh) { 1.91 + node->set_object(mesh); 1.92 + } 1.93 + } else if((elem = xml_node->FirstChildElement("light"))) { 1.94 + Light *lt = scn->get_light(elem->Attribute("string")); 1.95 + if(lt) { 1.96 + node->set_object(lt); 1.97 + } 1.98 + } else if((elem = xml_node->FirstChildElement("camera"))) { 1.99 + Camera *cam = scn->get_camera(elem->Attribute("string")); 1.100 + if(cam) { 1.101 + node->set_object(cam); 1.102 + } 1.103 + } 1.104 + 1.105 + float vec[4]; 1.106 + if((elem = xml_node->FirstChildElement("pos"))) { 1.107 + const char *val = elem->Attribute("float3"); 1.108 + if(val && sscanf(val, "%f %f %f", vec, vec + 1, vec + 2) == 3) { 1.109 + node->set_position(Vector3(val[0], val[1], val[2])); 1.110 + } else { 1.111 + logmsg(LOG_ERROR, "node %s: invalid position tag\n", node->get_name()); 1.112 + } 1.113 + } 1.114 + if((elem = xml_node->FirstChildElement("rot"))) { 1.115 + const char *val = elem->Attribute("float4"); 1.116 + if(val && sscanf(val, "%f %f %f %f", vec, vec + 1, vec + 2, vec + 3) == 4) { 1.117 + node->set_rotation(Quaternion(vec[3], Vector3(vec[0], vec[1], vec[2]))); 1.118 + } else { 1.119 + logmsg(LOG_ERROR, "node %s: invalid rotation tag\n", node->get_name()); 1.120 + } 1.121 + } 1.122 + if((elem = xml_node->FirstChildElement("scale"))) { 1.123 + const char *val = elem->Attribute("float3"); 1.124 + if(val && sscanf(val, "%f %f %f", vec, vec + 1, vec + 2) == 3) { 1.125 + node->set_scaling(Vector3(vec[0], vec[1], vec[2])); 1.126 + } else { 1.127 + logmsg(LOG_ERROR, "node %s: invalid scaling tag\n", node->get_name()); 1.128 + } 1.129 + } 1.130 + if((elem = xml_node->FirstChildElement("pivot"))) { 1.131 + const char *val = elem->Attribute("float3"); 1.132 + if(val && sscanf(val, "%f %f %f", vec, vec + 1, vec + 2) == 3) { 1.133 + node->set_pivot(Vector3(vec[0], vec[1], vec[2])); 1.134 + } else { 1.135 + logmsg(LOG_ERROR, "node %s: invalid pivot tag\n", node->get_name()); 1.136 + } 1.137 + } 1.138 + 1.139 + return node; 1.140 +} 1.141 + 1.142 +static std::string get_name(XMLElement *node, int idx, const char *def_prefix) 1.143 { 1.144 char buf[64]; 1.145 const char *name = 0; 1.146 @@ -237,7 +330,7 @@ 1.147 } 1.148 1.149 if(!name) { 1.150 - sprintf(buf, "mesh%04d", idx); 1.151 + sprintf(buf, "%s%04d", def_prefix, idx); 1.152 name = buf; 1.153 } 1.154