// --------------------------------------------------------------------------- // Includes for all the program files to see // --------------------------------------------------------------------------- #include #include #include using namespace std; #include // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- #include #include #include // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- #include #include #include #include "ViewCellsParser.h" #include "ViewCellsParserXerces.h" #include "Mesh.h" #include "VspBspTree.h" #include "ViewCellBsp.h" #include "VspKdTree.h" #include "ViewCellsManager.h" // --------------------------------------------------------------------------- // Local data // // doNamespaces // Indicates whether namespace processing should be enabled or not. // The default is no, but -n overrides that. // // doSchema // Indicates whether schema processing should be enabled or not. // The default is no, but -s overrides that. // // schemaFullChecking // Indicates whether full schema constraint checking should be enabled or not. // The default is no, but -s overrides that. // // valScheme // Indicates what validation scheme to use. It defaults to 'auto', but // can be set via the -v= command. // --------------------------------------------------------------------------- static bool doNamespaces = false; static bool doSchema = false; static bool schemaFullChecking = false; static SAXParser::ValSchemes valScheme = SAXParser::Val_Auto; // --------------------------------------------------------------------------- // StdInParseHandlers: Constructors and Destructor // --------------------------------------------------------------------------- ViewCellsParseHandlers::ViewCellsParseHandlers(ObjectContainer *objects): mElementCount(0) , mAttrCount(0) , mCharacterCount(0) , mSpaceCount(0) , mViewCellsManager(NULL) , mVspBspTree(NULL) , mBspTree(NULL) , mViewCellsTree(NULL) , mParseViewCells(true) , mCurrentViewCell(NULL) , mCurrentBspNode(NULL) { mObjects = objects; } ViewCellsParseHandlers::~ViewCellsParseHandlers() { } // --------------------------------------------------------------------------- // StdInParseHandlers: Implementation of the SAX DocumentHandler interface // --------------------------------------------------------------------------- void ViewCellsParseHandlers::endElement(const XMLCh* const name) { StrX lname(name); string element(lname.LocalForm()); if (element == "ViewCells") EndViewCells(); if (mParseViewCells) { if (element == "Interior") EndViewCellInterior(); } else { if (element == "Interior") EndBspInterior(); } } void ViewCellsParseHandlers::EndBspInterior() { // go one up in the tree if (mCurrentBspNode->GetParent()) { cout << "]"; mCurrentBspNode = mCurrentBspNode->GetParent(); } } void ViewCellsParseHandlers::EndViewCellInterior() { // go one up in the tree if (mCurrentViewCell->GetParent()) { cout << "]"; mCurrentViewCell = mCurrentViewCell->GetParent(); } } inline bool vlt(ViewCell *v1, ViewCell *v2) { return v1->mId < v2->mId; } void ViewCellsParseHandlers::EndViewCells() { // sort view cells to help associating view cells according to their id stable_sort(mViewCells.begin(), mViewCells.end(), vlt); } void ViewCellsParseHandlers::StartHierarchy(AttributeList& attributes) { int len = attributes.getLength(); for (int i = 0; i < len; ++ i) { string attrName(StrX(attributes.getName(i)).LocalForm()); if (attrName == "name") { StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); CreateViewCellsManager(ptr); } } } void ViewCellsParseHandlers::startBspElement(string element, AttributeList& attributes) { if (element == "Interior") { cout << "["; StartBspInterior(attributes); } if (element == "Leaf") { cout << "l"; Debug << "leaf" << endl; StartBspLeaf(attributes); } } void ViewCellsParseHandlers::startElement(const XMLCh* const name, AttributeList& attributes) { StrX lname(name); string element(lname.LocalForm()); // decides the used view cell hierarchy if (element == "ViewCells") { cout << "parsing view cells" << endl; mParseViewCells = true; } if (element == "Hierarchy") { cout << "parsing spatial hierarchy" << endl; mParseViewCells = false; StartHierarchy(attributes); } // decides the used view cell hierarchy if (element == "ViewSpaceBox") { cout << "b"; StartViewSpaceBox(attributes); } // use different methods for the given view cell hierarchy types if (!mParseViewCells) { if (mViewCellsManager) { switch (mViewCellsManager->GetType()) { case ViewCellsManager::BSP: case ViewCellsManager::VSP_BSP: startBspElement(element, attributes); break; default: Debug << "not implemented" << endl; break; } } } else { if (element == "Interior") { cout << "["; StartViewCellInterior(attributes); } if (element == "Leaf") { cout << "l"; StartViewCellLeaf(attributes); } } ++ mElementCount; mAttrCount += attributes.getLength(); } inline bool ilt(Intersectable *obj1, Intersectable *obj2) { return obj1->mId < obj2->mId; } void ViewCellsParseHandlers::StartViewCell(ViewCell *viewCell, AttributeList& attributes) { int len = attributes.getLength(); vector objIndices; for (int i = 0; i < len; ++ i) { string attrName(StrX(attributes.getName(i)).LocalForm()); if (attrName == "pvs") { StrX attrValue(attributes.getValue(i)); // handle coordIndex objIndices.clear(); const char *ptr = attrValue.LocalForm(); char *endptr; while (1) { int index = strtol(ptr, &endptr, 10); if (ptr == endptr) break; objIndices.push_back(index); ptr = endptr; } //TODO: find objects and add them to pvs // TODO: get view cell with specified id MeshInstance dummyInst(NULL); vector::const_iterator it, it_end = objIndices.end(); for (it = objIndices.begin(); it != it_end; ++ it) { const int objId = *it; dummyInst.SetId(objId); ObjectContainer::iterator oit = lower_bound(mObjects->begin(), mObjects->end(), &dummyInst, ilt); Intersectable *obj = *oit; if (obj->GetId() == objId) { // $$JB we should store a float a per object which corresponds // to sumof pdfs, i.e. its relative visibility // temporarily set to 1.0f viewCell->GetPvs().AddSample(obj, 1.0f); } else { Debug << "error: object does not exist" << endl; } } } else if (attrName == "id") { StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); char *endptr = NULL; const int id = strtol(ptr, &endptr, 10); viewCell->SetId(id); } else if (attrName == "active") { StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); char *endptr = NULL; const bool isActive = (bool)strtol(ptr, &endptr, 10); viewCell->mIsActive = isActive; } else if (attrName == "mergecost") { StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); char *endptr = NULL; const float cost = (float)strtod(ptr, &endptr); viewCell->SetMergeCost(cost); } } } void ViewCellsParseHandlers::StartViewSpaceBox(AttributeList& attributes) { int len = attributes.getLength(); Vector3 bmin, bmax; for (int i = 0; i < len; ++ i) { string attrName(StrX(attributes.getName(i)).LocalForm()); StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); if (attrName == "min") { sscanf(ptr, "%f %f %f", &bmin.x, &bmin.y, &bmin.z); } else if (attrName == "max") { sscanf(ptr, "%f %f %f", &bmax.x, &bmax.y, &bmax.z); } } mViewSpaceBox = AxisAlignedBox3(bmin, bmax); Debug << "view space box: " << mViewSpaceBox << endl; } void ViewCellsParseHandlers::StartBspLeaf(AttributeList& attributes) { BspLeaf * leaf = new BspLeaf(dynamic_cast(mCurrentBspNode), NULL); if (mCurrentBspNode) // replace front or (if not NULL) back child { dynamic_cast(mCurrentBspNode)->ReplaceChildLink(NULL, leaf); } else { if (mViewCellsManager->GetType() == ViewCellsManager::BSP) { mBspTree->mRoot = leaf; } else if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP) { mVspBspTree->mRoot = leaf; } } //-- find associated view cell int viewCellId; int len = attributes.getLength(); for (int i = 0; i < len; ++ i) { string attrName(StrX(attributes.getName(i)).LocalForm()); StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); char *endptr = NULL; if (attrName == "viewCellId") { viewCellId = strtol(ptr, &endptr, 10); } } Debug << "here22" << endl; if (viewCellId >= 0) // valid view cell { // TODO: get view cell with specified id ViewCellInterior dummyVc; dummyVc.SetId(viewCellId); ViewCellContainer::iterator vit = lower_bound(mViewCells.begin(), mViewCells.end(), &dummyVc, vlt); BspViewCell *viewCell = dynamic_cast(*vit); Debug << "here44" << endl; if (viewCell->GetId() == viewCellId) { leaf->SetViewCell(viewCell); viewCell->mLeaf = leaf; } else { Debug << "error: view cell does not exist" << endl; } } else { if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP) { leaf->SetViewCell(mVspBspTree->GetOrCreateOutOfBoundsCell()); leaf->SetTreeValid(false); mVspBspTree->PropagateUpValidity(leaf); } }Debug << "here33" << endl; } void ViewCellsParseHandlers::StartBspInterior(AttributeList& attributes) { Plane3 plane; int len = attributes.getLength(); for (int i = 0; i < len; ++ i) { string attrName(StrX(attributes.getName(i)).LocalForm()); StrX attrValue(attributes.getValue(i)); const char *ptr = attrValue.LocalForm(); if (attrName == "plane") { sscanf(ptr, "%f %f %f %f", &plane.mNormal.x, &plane.mNormal.y, &plane.mNormal.z, &plane.mD); } } BspInterior* interior = new BspInterior(plane); if (mCurrentBspNode) // replace NULL child of parent with current node { BspInterior *current = dynamic_cast(mCurrentBspNode); current->ReplaceChildLink(NULL, interior); interior->SetParent(current); } else { if (mViewCellsManager->GetType() == ViewCellsManager::BSP) { mBspTree->mRoot = interior; } else { mVspBspTree->mRoot = interior; } } mCurrentBspNode = interior; } void ViewCellsParseHandlers::StartViewCellLeaf(AttributeList& attributes) { Debug << "here111" << endl; BspViewCell *viewCell = new BspViewCell(); if (mCurrentViewCell) // replace front or (if not NULL) back child { ViewCellInterior *interior = dynamic_cast(mCurrentViewCell); interior->SetupChildLink(viewCell); } else // root { mViewCellsTree->SetRoot(viewCell); } StartViewCell(viewCell, attributes); // collect leaves mViewCells.push_back(viewCell); } void ViewCellsParseHandlers::StartViewCellInterior(AttributeList& attributes) { Debug << "here222" << endl; ViewCellInterior* interior = new ViewCellInterior(); if (mCurrentViewCell) // replace NULL child of parent with current node { ViewCellInterior *current = dynamic_cast(mCurrentViewCell); current->SetupChildLink(interior); } else { mViewCellsTree->SetRoot(interior); } mCurrentViewCell = interior; StartViewCell(interior, attributes); } void ViewCellsParseHandlers::CreateViewCellsManager(const char *name) { if (strcmp(name, "bspTree") == 0) { Debug << "view cell type: Bsp" << endl; mBspTree = new BspTree(); mBspTree->mBox = mViewSpaceBox; //mCurrentBspNode = mBspTree->GetRoot(); mViewCellsManager = new BspViewCellsManager(mBspTree); } else if (strcmp(name, "vspBspTree") == 0) { Debug << "view cell type: VspBsp" << endl; mVspBspTree = new VspBspTree(); //mCurrentBspNode = mVspBspTree->GetRoot(); mViewCellsManager = new VspBspViewCellsManager(mVspBspTree); mVspBspTree->mBox = mViewSpaceBox; Debug << "creating vsp bsp view cells manager" << endl; } else if (strcmp(name, "vspKdTree") == 0) { // TODO mVspKdTree = new VspKdTree(); mViewCellsManager = new VspKdViewCellsManager(mVspKdTree); } else { cerr<<"Wrong view cells type" << name << endl; exit(1); } mViewCellsTree = mViewCellsManager->GetViewCellsTree(); mViewCellsManager->SetViewSpaceBox(mViewSpaceBox); } void ViewCellsParseHandlers::characters(const XMLCh* const chars, const unsigned int length) { mCharacterCount += length; } void ViewCellsParseHandlers::ignorableWhitespace(const XMLCh* const chars, const unsigned int length) { mSpaceCount += length; } void ViewCellsParseHandlers::resetDocument() { mAttrCount = 0; mCharacterCount = 0; mElementCount = 0; mSpaceCount = 0; } // --------------------------------------------------------------------------- // StdInParseHandlers: Overrides of the SAX ErrorHandler interface // --------------------------------------------------------------------------- void ViewCellsParseHandlers::error(const SAXParseException& e) { XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId()) << ", line " << e.getLineNumber() << ", char " << e.getColumnNumber() << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl; } void ViewCellsParseHandlers::fatalError(const SAXParseException& e) { XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId()) << ", line " << e.getLineNumber() << ", char " << e.getColumnNumber() << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl; } void ViewCellsParseHandlers::warning(const SAXParseException& e) { XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId()) << ", line " << e.getLineNumber() << ", char " << e.getColumnNumber() << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl; } bool ViewCellsParser::ParseFile(const string filename, ViewCellsManager **viewCells, ObjectContainer *objects) { // Initialize the XML4C system try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n" << StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl; return false; } // // Create a SAX parser object. Then, according to what we were told on // the command line, set the options. // SAXParser* parser = new SAXParser; parser->setValidationScheme(valScheme); parser->setDoNamespaces(doNamespaces); parser->setDoSchema(doSchema); parser->setValidationSchemaFullChecking(schemaFullChecking); // // Create our SAX handler object and install it on the parser, as the // document and error handler. We are responsible for cleaning them // up, but since its just stack based here, there's nothing special // to do. // ViewCellsParseHandlers handler(objects); parser->setDocumentHandler(&handler); parser->setErrorHandler(&handler); unsigned long duration; int errorCount = 0; // create a faux scope so that 'src' destructor is called before // XMLPlatformUtils::Terminate { // // Kick off the parse and catch any exceptions. Create a standard // input input source and tell the parser to parse from that. // // StdInInputSource src; try { const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis(); parser->parse(filename.c_str()); const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis(); duration = endMillis - startMillis; errorCount = parser->getErrorCount(); } catch (const OutOfMemoryException&) { XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl; errorCount = 2; return false; } catch (const XMLException& e) { XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n" << StrX(e.getMessage()) << "\n" << XERCES_STD_QUALIFIER endl; errorCount = 1; return false; } // Print out the stats that we collected and time taken if (!errorCount) { XERCES_STD_QUALIFIER cout << filename << ": " << duration << " ms (" << handler.GetElementCount() << " elems, " << handler.GetAttrCount() << " attrs, " << handler.GetSpaceCount() << " spaces, " << handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl; } } // // Delete the parser itself. Must be done prior to calling Terminate, below. // delete parser; XMLPlatformUtils::Terminate(); // assign new view cells manager *viewCells = handler.mViewCellsManager; if (errorCount > 0) return false; else return true; }