bool XMLScene::parseNode(TiXmlElement *curr_node, bool is_inside_dl) { char node_id[MAX_STRING_LEN]; if (strdup(node_id, curr_node->Attribute("id")) == NULL) { printf("Error reading \"id\" attribute!\n"); throw InvalidXMLException(); } printf("id: %s\n", node_id); bool is_dl = false; string dl_node_id; if (curr_node->QueryBoolAttribute("displaylist", &is_dl) != TIXML_SUCCESS) { printf("No \"displaylist\" attribute\n"); } if (is_dl) { printf("Node \"%s\" defined as a display list.\n", node_id); dl_node_id = Scene::getInstance()->findNextNameAvail(node_id); printf("dl_node_id: %s\n", dl_node_id.c_str()); } Node *n; if (is_dl) { n = new DisplayList(dl_node_id); } else { n = new Node(node_id); } nodes_being_processed.push_back(node_id); printf("Processing transformations...\n"); TiXmlElement *transf_block = NULL; if ((transf_block = curr_node->FirstChildElement("transforms")) == NULL) { printf("Could not find \"transforms\" block on %s node!\n", node_id); throw InvalidXMLException(); } TiXmlElement *transf = NULL; while ((transf = (TiXmlElement*) transf_block->IterateChildren(transf))) { char t_type[MAX_STRING_LEN]; if (strdup(t_type, transf->Value()) == NULL) { printf("Invalid transformation on node %s\n", node_id); throw InvalidXMLException(); } if (strcmp(t_type, "translate") == 0) { char tmp_str[MAX_STRING_LEN]; double t_x = 0, t_y = 0, t_z = 0; if (strdup(tmp_str, transf->Attribute("to")) == NULL) { printf("Error on translate transformation on node %s!\n", node_id); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf %lf", &t_x, &t_y, &t_z) != 3) { printf("Error parsing translate transformation on node %s!\n", node_id); throw InvalidXMLException(); } n->addTranslate(t_x, t_y, t_z); printf("Translate\nto: (%f %f %f)\n", t_x, t_y, t_z); } else if (strcmp(t_type, "rotate") == 0) { char tmp_str[2]; char r_axis = '\0'; double r_angle; if (strdup(tmp_str, transf->Attribute("axis")) == NULL) { printf("Error on rotate transformation on node %s!\n", node_id); throw InvalidXMLException(); } r_axis = tmp_str[0]; if (transf->QueryDoubleAttribute("angle", &r_angle)) { printf("Error parsing rotate transformation on node %s!\n", node_id); throw InvalidXMLException(); } n->addRotation(r_angle, r_axis); printf("Rotate\naxis: %c\nangle: %f\n", r_axis, r_angle); } else if (strcmp(t_type, "scale") == 0) { char tmp_str[MAX_STRING_LEN]; double f_x = 0, f_y = 0, f_z = 0; if (strdup(tmp_str, transf->Attribute("factor")) == NULL) { printf("Error on scale transformation on node %s!\n", node_id); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf %lf", &f_x, &f_y, &f_z) != 3) { printf("Error parsing scale transformation on node %s!\n", node_id); throw InvalidXMLException(); } n->addScale(f_x, f_y, f_z); printf("Scale\nfactor: (%f %f %f)\n", f_x, f_y, f_z); } else { printf("Invalid transformation on node %s\n", node_id); throw InvalidXMLException(); } } TiXmlElement *appearance = NULL; if ((appearance = curr_node->FirstChildElement("appearanceref"))) { char app_id[MAX_STRING_LEN]; if (strdup(app_id, appearance->Attribute("id")) == NULL) { printf("Error on \"appearanceref\" block on node %s!\n", node_id); throw InvalidXMLException(); } n->setAppearance(app_id); app_stck.push(app_id); printf("Appearance\nid: %s\n", app_id); } else { app_stck.push(app_stck.top()); } TiXmlElement *animation = NULL; if ((animation = curr_node->FirstChildElement("animationref"))) { if (is_inside_dl || is_dl) { printf("Animation defined in \"%s\" is inside a display list!\n", node_id); throw InvalidXMLException(); } char ani_id[MAX_STRING_LEN]; if (strdup(ani_id, animation->Attribute("id")) == NULL) { printf("Error on \"animationref\" block on node %s!\n", node_id); throw InvalidXMLException(); } n->setAnimation(ani_id); printf("Animation\nid: %s\n", ani_id); } else { printf("No animation defined on node \"%s\".\n", node_id); } printf("Processing children...\n"); TiXmlElement *children = NULL; if ((children = curr_node->FirstChildElement("children")) == NULL) { printf("Block \"children\" not found!\n"); throw InvalidXMLException(); } TiXmlElement *child = NULL; while ((child = (TiXmlElement *) children->IterateChildren(child))) { char child_type[MAX_STRING_LEN]; strdup(child_type, child->Value()); if (strcmp(child_type, "rectangle") == 0) { char tmp_str[MAX_STRING_LEN]; double x1 = 0, x2 = 0, y1 = 0, y2 = 0; if (strdup(tmp_str, child->Attribute("xy1")) == NULL) { printf("Error reading \"xy1\" attribute!\n"); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf", &x1, &y1) != 2) { printf("Error parsing \"xy1\" attribute!\n"); throw InvalidXMLException(); } if (strdup(tmp_str, child->Attribute("xy2")) == NULL) { printf("Error reading \"xy2\" attribute!\n"); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf", &x2, &y2) != 2) { printf("Error parsing \"xy2\" attribute!\n"); throw InvalidXMLException(); } MyRectangle *rect = new MyRectangle(x1, y1, x2, y2); n->addPrimitive(rect); printf("Rectangle\nxy1: (%f,%f)\nxy2: (%f,%f)\n", x1, y1, x2, y2); } else if (strcmp(child_type, "triangle") == 0) { char tmp_str[MAX_STRING_LEN]; double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, y3 = 0, z1 = 0, z2 = 0, z3 = 0; if (strdup(tmp_str, child->Attribute("xyz1")) == NULL) { printf("Error reading \"xyz1\" attribute!\n"); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf %lf", &x1, &y1, &z1) != 3) { printf("Error parsing \"xyz1\" attribute!\n"); throw InvalidXMLException(); } if (strdup(tmp_str, child->Attribute("xyz2")) == NULL) { printf("Error reading \"xyz2\" attribute!\n"); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf %lf", &x2, &y2, &z2) != 3) { printf("Error parsing \"xyz2\" attribute!\n"); throw InvalidXMLException(); } if (strdup(tmp_str, child->Attribute("xyz3")) == NULL) { printf("Error reading \"xyz3\" attribute!\n"); throw InvalidXMLException(); } if (sscanf(tmp_str, "%lf %lf %lf", &x3, &y3, &z3) != 3) { printf("Error parsing \"xyz3\" attribute!\n"); throw InvalidXMLException(); } MyTriangle *tri = new MyTriangle(x1, y1, z1, x2, y2, z2, x3, y3, z3); n->addPrimitive(tri); printf("Triangle\nxyz1: (%f,%f,%f)\nxyz2: (%f,%f,%f)\nxyz3: (%f,%f,%f)\n", x1, y1, z1, x2, y2, z2, x3, y3, z3); } else if (strcmp(child_type, "cylinder") == 0) { double cyl_base = 0, cyl_top = 0, cyl_height = 0; unsigned int cyl_slices = 0, cyl_stacks = 0; if (child->QueryDoubleAttribute("base", &cyl_base) != TIXML_SUCCESS) { printf("Error parsing base attribute!\n"); throw InvalidXMLException(); } if (child->QueryDoubleAttribute("top", &cyl_top) != TIXML_SUCCESS) { printf("Error parsing slices attribute!\n"); throw InvalidXMLException(); } if (child->QueryDoubleAttribute("height", &cyl_height) != TIXML_SUCCESS) { printf("Error parsing slices attribute!\n"); throw InvalidXMLException(); } if (child->QueryUnsignedAttribute("slices", &cyl_slices) != TIXML_SUCCESS) { printf("Error parsing slices attribute!\n"); throw InvalidXMLException(); } if (child->QueryUnsignedAttribute("stacks", &cyl_stacks) != TIXML_SUCCESS) { printf("Error parsing stacks attribute!\n"); throw InvalidXMLException(); } MyCylinder *cyl = new MyCylinder(cyl_base, cyl_top, cyl_height, cyl_slices, cyl_stacks); n->addPrimitive(cyl); printf("Cylinder\nbase: %f\ntop: %f\nheight: %f\nslices: %d\nstacks: %d\n", cyl_base, cyl_top, cyl_height, cyl_slices, cyl_stacks); } else if (strcmp(child_type, "sphere") == 0) { double sph_rad = 0; unsigned int sph_slices = 0, sph_stacks = 0; if (child->QueryDoubleAttribute("radius", &sph_rad) != TIXML_SUCCESS) { printf("Error parsing radius attribute!\n"); } if (child->QueryUnsignedAttribute("slices", &sph_slices) != TIXML_SUCCESS) { printf("Error parsing slices attribute!\n"); } if (child->QueryUnsignedAttribute("stacks", &sph_stacks) != TIXML_SUCCESS) { printf("Error parsing stacks attribute!\n"); } MySphere *sph = new MySphere(sph_rad, sph_slices, sph_stacks); n->addPrimitive(sph); printf("Sphere\nradius: %f\nslices: %d\nstacks: %d\n", sph_rad, sph_slices, sph_stacks); } else if (strcmp(child_type, "torus") == 0) { double tor_inner = 0, tor_out = 0; unsigned int tor_slices = 0, tor_loops = 0; if (child->QueryDoubleAttribute("inner", &tor_inner) != TIXML_SUCCESS) { printf("Error parsing inner attribute!\n"); } if (child->QueryDoubleAttribute("outer", &tor_out) != TIXML_SUCCESS) { printf("Error parsing outer attribute!\n"); } if (child->QueryUnsignedAttribute("slices", &tor_slices) != TIXML_SUCCESS) { printf("Error parsing slices attribute!\n"); } if (child->QueryUnsignedAttribute("loops", &tor_loops) != TIXML_SUCCESS) { printf("Error parsing loops attribute!\n"); } MyTorus *tor = new MyTorus(tor_inner, tor_out, tor_slices, tor_loops); n->addPrimitive(tor); printf("Torus\ninner: %f\nouter: %f\nslices: %d\nloops: %d\n", tor_inner, tor_out, tor_slices, tor_loops); } else if (strcmp(child_type, "plane") == 0) { int parts = 0; if (child->QueryIntAttribute("parts", &parts) != TIXML_SUCCESS) { printf("Error parsing \"parts\" attribute on plane!\n"); throw InvalidXMLException(); } if (parts <= 0) { printf("Invalid value on parts attribute of plane!\n"); throw InvalidXMLException(); } printf("Plane\nparts: %i\n", parts); Plane *p = new Plane(parts); n->addPrimitive(p); } else if (strcmp(child_type, "patch") == 0) { int order = 0; int parts_u = 0; int parts_v = 0; char compute[MAX_STRING_LEN]; if (child->QueryIntAttribute("order", &order) != TIXML_SUCCESS) { printf("Error parsing \"order\" attribute on patch!\n"); throw InvalidXMLException(); } if (child->QueryIntAttribute("partsU", &parts_u) != TIXML_SUCCESS) { printf("Error parsing \"partsU\" attribute on patch!\n"); throw InvalidXMLException(); } if (child->QueryIntAttribute("partsV", &parts_v) != TIXML_SUCCESS) { printf("Error parsing \"partsV\" attribute on patch!\n"); throw InvalidXMLException(); } if (strdup(compute, child->Attribute("compute")) == NULL) { printf("Error parsing \"compute\" attribute on patch!\n"); throw InvalidXMLException(); } printf("Patch\norder: %d\npartsU: %d\npartsV: %d\ncompute: %s\n", order, parts_u, parts_v, compute); MyPatch *patch = new MyPatch(order, parts_u, parts_v, compute); n->addPrimitive(patch); TiXmlElement *ctrl_p = child->FirstChildElement("controlpoint"); do { float x = 0; float y = 0; float z = 0; if (ctrl_p->QueryFloatAttribute("x", &x) != TIXML_SUCCESS) { printf("Error parsing \"x\" attribute on patch!\n"); throw InvalidXMLException(); } if (ctrl_p->QueryFloatAttribute("y", &y) != TIXML_SUCCESS) { printf("Error parsing \"y\" attribute on patch!\n"); throw InvalidXMLException(); } if (ctrl_p->QueryFloatAttribute("z", &z) != TIXML_SUCCESS) { printf("Error parsing \"z\" attribute on patch!\n"); throw InvalidXMLException(); } printf("controlpoint: (%f %f %f)\n", x, y, z); patch->addControlPoint(x, y, z); } while ((ctrl_p = ctrl_p->NextSiblingElement("controlpoint")) != NULL); } else if (strcmp(child_type, "waterline") == 0) { char heightmap[MAX_STRING_LEN]; char texturemap[MAX_STRING_LEN]; char vert_shader[MAX_STRING_LEN]; char frag_shader[MAX_STRING_LEN]; if (is_inside_dl || is_dl) { printf("Waterline defined in \"%s\" is inside a display list!\n", node_id); throw InvalidXMLException(); } if (strdup(heightmap, child->Attribute("heightmap")) == NULL) { printf("Error parsing \"heightmap\" attribute of waterline!"); throw InvalidXMLException(); } if (strdup(texturemap, child->Attribute("texturemap")) == NULL) { printf("Error parsing \"texturemap\" attribute of waterline!"); throw InvalidXMLException(); } if (strdup(frag_shader, child->Attribute("fragmentshader")) == NULL) { printf("Error parsing \"fragmentshader\" attribute of waterline!"); throw InvalidXMLException(); } if (strdup(vert_shader, child->Attribute("vertexshader")) == NULL) { printf("Error parsing \"vertexshader\" attribute of waterline!"); throw InvalidXMLException(); } MyWaterLine *wl = new MyWaterLine(heightmap, texturemap, vert_shader, frag_shader); n->addPrimitive(wl); } else if (strcmp(child_type, "vehicle") == 0) { MyVehicle *v = new MyVehicle(); n->addPrimitive(v); } else if (strcmp(child_type, "noderef") == 0) { char next_node_id[MAX_STRING_LEN]; if (strdup(next_node_id, child->Attribute("id")) == NULL) { printf("Error reading noderef's id!\n"); throw InvalidXMLException(); } if (find(nodes_being_processed.begin(), nodes_being_processed.end(), next_node_id) != nodes_being_processed.end()) { if (find(nodes_finished_processing.begin(), nodes_finished_processing.end(), next_node_id) != nodes_finished_processing.end()) { printf("Node has already been processed.\n"); string last_node_name = Scene::getInstance()->findLastNameAvail(next_node_id); if (Scene::getInstance()->getNode(last_node_name)->getType() != DISPLAY_LIST) { // normal node n->addRef(next_node_id); } else { TiXmlElement *next_node = NULL; if ((next_node = findChildByAttribute(graphElement, "id", next_node_id))) { printf("\n\n"); parseNode(next_node, is_dl || is_inside_dl); n->addRef(Scene::getInstance()->findLastNameAvail(next_node_id)); } } continue; } else { printf("Cyclic definition found in node \"%s\"", next_node_id); throw InvalidXMLException(); } } else { TiXmlElement *next_node = NULL; if ((next_node = findChildByAttribute(graphElement, "id", next_node_id))) { printf("\n\n"); parseNode(next_node, is_dl || is_inside_dl); string last_node_name = Scene::getInstance()->findLastNameAvail(next_node_id); if (Scene::getInstance()->getNode(last_node_name)->getType() == DISPLAY_LIST) { n->addRef(last_node_name); } else { n->addRef(next_node_id); } } else { printf("Node %s does not exist!\n", next_node_id); throw InvalidXMLException(); } } } else { printf("Invalid block inside children of node %s\n", node_id); throw InvalidXMLException(); } } printf("Finished processing %s node children.\n\n", node_id); if (is_dl) { Scene::getInstance()->addNode(dl_node_id, n); } else { Scene::getInstance()->addNode(node_id, n); } printf("closing %s\n", node_id); n->closeDefinition(app_stck); printf("closed %s\n", node_id); app_stck.pop(); nodes_finished_processing.push_back(node_id); return true; }