// --------------------------------------------------------------------------- // 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 "ViewCellsManager.h" #include "GzFileInputSource.h" #include "VspOspTree.h" namespace GtpVisibilityPreprocessor { // --------------------------------------------------------------------------- // 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, BoundingBoxConverter *bconverter): mElementCount(0) , mAttrCount(0) , mCharacterCount(0) , mSpaceCount(0) , mViewCellsManager(NULL) , mVspBspTree(NULL) , mBspTree(NULL) , mViewCellsTree(NULL) , mParseViewCells(true) , mCurrentViewCell(NULL) , mCurrentBspNode(NULL) , mObjects(objects) , mBoundingBoxConverter(bconverter) { } 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 (element == "BoundingBoxes") EndBoundingBoxes(); // inside the view cell description if (mParseViewCells) { if (element == "Interior") EndViewCellInterior(); } else { if (element == "Interior") EndBspInterior(); } } void ViewCellsParseHandlers::EndBspInterior() { // go one up in the tree if (mCurrentBspNode->GetParent()) { Debug << "]"; mCurrentBspNode = mCurrentBspNode->GetParent(); } } void ViewCellsParseHandlers::EndViewCellInterior() { // go one up in the tree if (mCurrentViewCell->GetParent()) { Debug << "]"; mCurrentViewCell = mCurrentViewCell->GetParent(); } } inline static 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); mParseViewCells = false; } void ViewCellsParseHandlers::EndBoundingBoxes() { // all bounding boxes gathered in this step => // associate object ids with bounding boxes long startTime = GetTime(); if (mBoundingBoxConverter) mBoundingBoxConverter->IdentifyObjects(mIBoundingBoxes, *mObjects); Debug << "\nconverted bounding boxes to objects in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl; } 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(); //-- the view cells manager is created here CreateViewCellsManager(ptr); } } } void ViewCellsParseHandlers::startBspElement(string element, AttributeList& attributes) { if (element == "Interior") { Debug << "["; StartBspInterior(attributes); } if (element == "Leaf") { Debug << "l"; StartBspLeaf(attributes); } } void ViewCellsParseHandlers::startElement(const XMLCh* const name, AttributeList& attributes) { StrX lname(name); string element(lname.LocalForm()); if (element == "ViewCells") { Debug << "parsing view cells" << endl; mParseViewCells = true; } // decides about the view cell hierarchy if (element == "HierarchyType") //if (element == "Hierarchy") { //Debug << "parsing spatial hierarchy" << endl; //mParseViewCells = false; StartHierarchy(attributes); } // decides the used view cell hierarchy if (element == "ViewSpaceBox") { Debug << "v"; StartViewSpaceBox(attributes); } // decides the used view cell hierarchy if (element == "BoundingBox") { Debug << "b"; StartBoundingBox(attributes); } if (!mParseViewCells) { //-- use different methods for the given view cell hierarchy types if (mViewCellsManager) { switch (mViewCellsManager->GetType()) { case ViewCellsManager::BSP: case ViewCellsManager::VSP_BSP: startBspElement(element, attributes); break; default: Debug << "not implemented" << endl; break; } } } else { // interiors + leaves interpreted view cells else if (element == "Interior") { Debug << "["; StartViewCellInterior(attributes); } if (element == "Leaf") { Debug << "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(), (Intersectable *)&dummyInst, ilt); if ((oit != mObjects->end()) && ((*oit)->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(*oit, 1.0f); } else { Debug << "error: object with id " << objId << " 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); if (isActive) viewCell->SetActive(); }*/ 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 << "\nview space box: " << mViewSpaceBox << endl; } void ViewCellsParseHandlers::StartBoundingBox(AttributeList& attributes) { int len = attributes.getLength(); Vector3 bmin, bmax; int id; 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 == "id") { sscanf(ptr, "%d", &id); } 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); } } AxisAlignedBox3 box(bmin, bmax); mIBoundingBoxes.push_back(IndexedBoundingBox(id, box)); //Debug << "bbox: " << box << 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); } } 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); if (viewCell->GetId() == viewCellId) { leaf->SetViewCell(viewCell); viewCell->mLeaf = leaf; } else { Debug << "error: view cell does not exist" << endl; } } else { // add to invalid view space if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP) { leaf->SetViewCell(mVspBspTree->GetOrCreateOutOfBoundsCell()); leaf->SetTreeValid(false); mVspBspTree->PropagateUpValidity(leaf); } } } 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) { 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) { 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; } else if (strcmp(name, "vspOspTree") == 0) { Debug << "view cell type: VspOsp" << endl; mVspTree = new VspTree(); mOspTree = new OspTree(); //mCurrentBspNode = mVspBspTree->GetRoot(); mViewCellsManager = new VspOspViewCellsManager(mVspTree, mOspTree); mVspTree->mBoundingBox = mViewSpaceBox; } 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, BoundingBoxConverter *bconverter) { // 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, bconverter); 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(); #if ZIPPED_VIEWCELLS XMLCh *myFilePath = XMLString::transcode(filename.c_str()); GzFileInputSource isource(myFilePath); parser->parse(isource); #else parser->parse(filename.c_str()); #endif 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 cerr << 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; } }