Example #1
0
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;
}