source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp @ 1006

Revision 1006, 19.4 KB checked in by mattausch, 18 years ago (diff)

started viewspace-objectspace subdivision
removed memory leaks

Line 
1// ---------------------------------------------------------------------------
2//  Includes for all the program files to see
3// ---------------------------------------------------------------------------
4#include <string.h>
5#include <stdlib.h>
6#include <iostream>
7using namespace std;
8#include <xercesc/util/PlatformUtils.hpp>
9
10// ---------------------------------------------------------------------------
11//  Includes
12// ---------------------------------------------------------------------------
13#include <xercesc/framework/StdInInputSource.hpp>
14#include <xercesc/parsers/SAXParser.hpp>
15#include <xercesc/util/OutOfMemoryException.hpp>
16
17// ---------------------------------------------------------------------------
18//  Includes
19// ---------------------------------------------------------------------------
20#include <xercesc/sax/AttributeList.hpp>
21#include <xercesc/sax/SAXParseException.hpp>
22#include <xercesc/sax/SAXException.hpp>
23
24#include "ViewCellsParser.h"
25
26#include "ViewCellsParserXerces.h"
27#include "Mesh.h"
28#include "VspBspTree.h"
29#include "ViewCellBsp.h"
30#include "ViewCellsManager.h"
31#include "GzFileInputSource.h"
32
33namespace GtpVisibilityPreprocessor {
34
35
36// ---------------------------------------------------------------------------
37//  Local data
38//
39//  doNamespaces
40//      Indicates whether namespace processing should be enabled or not.
41//      The default is no, but -n overrides that.
42//
43//  doSchema
44//      Indicates whether schema processing should be enabled or not.
45//      The default is no, but -s overrides that.
46//
47//  schemaFullChecking
48//      Indicates whether full schema constraint checking should be enabled or not.
49//      The default is no, but -s overrides that.
50//
51//  valScheme
52//      Indicates what validation scheme to use. It defaults to 'auto', but
53//      can be set via the -v= command.
54// ---------------------------------------------------------------------------
55static bool     doNamespaces       = false;
56static bool     doSchema           = false;
57static bool     schemaFullChecking = false;
58static SAXParser::ValSchemes    valScheme       = SAXParser::Val_Auto;
59
60
61
62
63
64// ---------------------------------------------------------------------------
65//  StdInParseHandlers: Constructors and Destructor
66// ---------------------------------------------------------------------------
67ViewCellsParseHandlers::ViewCellsParseHandlers(ObjectContainer *objects,
68                                                                                           BoundingBoxConverter *bconverter):
69  mElementCount(0)
70  , mAttrCount(0)
71  , mCharacterCount(0)
72  , mSpaceCount(0)
73  , mViewCellsManager(NULL)
74  , mVspBspTree(NULL)
75  , mBspTree(NULL)
76  , mViewCellsTree(NULL)
77  , mParseViewCells(true)
78  , mCurrentViewCell(NULL)
79  , mCurrentBspNode(NULL)
80  , mObjects(objects)
81  , mBoundingBoxConverter(bconverter)
82{
83}
84
85
86ViewCellsParseHandlers::~ViewCellsParseHandlers()
87{
88}
89
90
91// ---------------------------------------------------------------------------
92//  StdInParseHandlers: Implementation of the SAX DocumentHandler interface
93// ---------------------------------------------------------------------------
94
95
96void ViewCellsParseHandlers::endElement(const XMLCh* const name)
97{
98  StrX lname(name);
99  string element(lname.LocalForm());
100
101  if (element == "ViewCells")
102          EndViewCells();
103
104  if (element == "BoundingBoxes")
105          EndBoundingBoxes();
106
107  // inside the view cell description
108  if (mParseViewCells)
109  {
110          if (element == "Interior")
111                  EndViewCellInterior();
112  }
113  else
114  {
115          if (element == "Interior")
116                  EndBspInterior();
117  }
118}
119
120
121void ViewCellsParseHandlers::EndBspInterior()
122{
123        // go one up in the tree
124        if (mCurrentBspNode->GetParent())
125        {       Debug << "]";
126                mCurrentBspNode = mCurrentBspNode->GetParent();
127        }
128}
129
130
131void ViewCellsParseHandlers::EndViewCellInterior()
132{
133        // go one up in the tree
134        if (mCurrentViewCell->GetParent())
135        {       Debug << "]";
136                mCurrentViewCell = mCurrentViewCell->GetParent();
137        }
138}
139
140
141inline static bool vlt(ViewCell *v1, ViewCell *v2)
142{
143        return v1->mId < v2->mId;
144}
145
146
147void ViewCellsParseHandlers::EndViewCells()
148{
149        // sort view cells to help associating view cells according to their id
150        stable_sort(mViewCells.begin(), mViewCells.end(), vlt);
151        mParseViewCells = false;
152}
153
154
155void ViewCellsParseHandlers::EndBoundingBoxes()
156{
157        // all bounding boxes gathered in this step =>
158        // associate object ids with bounding boxes
159        long startTime = GetTime();
160       
161        if (mBoundingBoxConverter)
162                mBoundingBoxConverter->IdentifyObjects(mIBoundingBoxes, *mObjects);
163
164        Debug << "\nconverted bounding boxes to objects in "
165                  << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
166}
167
168
169void ViewCellsParseHandlers::StartHierarchy(AttributeList&  attributes)
170{
171        int len = attributes.getLength();
172 
173        for (int i = 0; i < len; ++ i)
174        {
175                string attrName(StrX(attributes.getName(i)).LocalForm());
176               
177                if (attrName == "name")
178                {
179                        StrX attrValue(attributes.getValue(i));
180                       
181                        const char *ptr = attrValue.LocalForm();
182                       
183                        //-- the view cells manager is created here
184                        CreateViewCellsManager(ptr);
185                }
186        }
187}
188
189
190void ViewCellsParseHandlers::startBspElement(string element,
191                                                                                         AttributeList& attributes)
192{
193        if (element == "Interior")
194        {
195                Debug << "[";
196                StartBspInterior(attributes);
197        }
198
199        if (element == "Leaf")
200        {
201                Debug << "l";
202                StartBspLeaf(attributes);
203        }
204}
205
206
207void ViewCellsParseHandlers::startElement(const XMLCh* const name,
208                                                                                  AttributeList& attributes)
209{
210        StrX lname(name);
211        string element(lname.LocalForm());
212
213
214        if (element == "ViewCells")
215        {
216                Debug << "parsing view cells" << endl;
217                mParseViewCells = true;
218        }
219
220        // decides about the view cell hierarchy
221        if (element == "HierarchyType")
222        //if (element == "Hierarchy")
223        {
224                //Debug << "parsing spatial hierarchy" << endl;
225                //mParseViewCells = false;
226                StartHierarchy(attributes);
227        }
228       
229        // decides the used view cell hierarchy
230        if (element == "ViewSpaceBox")
231        {
232                Debug << "v";
233                StartViewSpaceBox(attributes);
234        }
235
236        // decides the used view cell hierarchy
237        if (element == "BoundingBox")
238        {
239                Debug << "b";
240                StartBoundingBox(attributes);
241        }
242
243       
244        if (!mParseViewCells)
245        {
246                //-- use different methods for the given view cell hierarchy types
247                if (mViewCellsManager)
248                {
249                        switch (mViewCellsManager->GetType())
250                        {
251                        case ViewCellsManager::BSP:
252                        case ViewCellsManager::VSP_BSP:
253                                startBspElement(element, attributes);
254                                break;
255       
256                        default:
257                                Debug << "not implemented" << endl;
258                                break;
259                        }
260                }
261        }
262        else
263        {
264                // interiors + leaves interpreted view cells else
265                if (element == "Interior")
266                {
267                        Debug << "[";
268                        StartViewCellInterior(attributes);
269                }
270
271                if (element == "Leaf")
272                {
273                        Debug << "l";
274                        StartViewCellLeaf(attributes);
275                }
276        }
277
278        ++ mElementCount;
279        mAttrCount += attributes.getLength();
280}
281
282
283inline bool ilt(Intersectable *obj1, Intersectable *obj2)
284{
285        return obj1->mId < obj2->mId;
286}
287
288
289void ViewCellsParseHandlers::StartViewCell(ViewCell *viewCell, AttributeList&  attributes)
290{
291        int len = attributes.getLength();
292        vector<int> objIndices;
293
294        for (int i = 0; i < len; ++ i)
295        {
296                string attrName(StrX(attributes.getName(i)).LocalForm());
297               
298                if (attrName == "pvs")
299                {
300                        StrX attrValue(attributes.getValue(i));
301                       
302                        // handle coordIndex
303                        objIndices.clear();
304                        const char *ptr = attrValue.LocalForm();
305                        char *endptr;
306                       
307                        while (1)
308                        {
309                                int index = strtol(ptr, &endptr, 10);
310
311                                if (ptr == endptr)
312                                        break;
313
314                                objIndices.push_back(index);
315
316                                ptr = endptr;
317                        }
318
319                        //TODO: find objects and add them to pvs
320                        // TODO: get view cell with specified id
321                        MeshInstance dummyInst(NULL);
322
323                        vector<int>::const_iterator it, it_end = objIndices.end();
324                        for (it = objIndices.begin(); it != it_end; ++ it)
325                        {
326                                const int objId = *it; 
327                                dummyInst.SetId(objId);
328
329                                ObjectContainer::iterator oit =
330                                  lower_bound(mObjects->begin(), mObjects->end(), (Intersectable *)&dummyInst, ilt);
331                               
332                                                       
333                                if ((oit != mObjects->end()) && ((*oit)->GetId() == objId))
334                                {
335                                        // $$JB we should store a float a per object which corresponds
336                                        // to sumof pdfs, i.e. its relative visibility
337                                        // temporarily set to 1.0f
338                                        viewCell->GetPvs().AddSample(*oit, 1.0f);                               
339                                }
340                                else
341                                {
342                                        Debug << "error: object with id " << objId << " does not exist" << endl;
343                                }
344                        }
345                }
346                else if (attrName == "id")
347                {
348                        StrX attrValue(attributes.getValue(i));
349                       
350                        const char *ptr = attrValue.LocalForm();
351                        char *endptr = NULL;
352                        const int id = strtol(ptr, &endptr, 10);
353
354                        viewCell->SetId(id);
355                }
356                /*else if (attrName == "active")
357                {
358                        StrX attrValue(attributes.getValue(i));
359                       
360                        const char *ptr = attrValue.LocalForm();
361                        char *endptr = NULL;
362                        const bool isActive = (bool)strtol(ptr, &endptr, 10);
363
364                        if (isActive)
365                                viewCell->SetActive();
366                }*/
367                else if (attrName == "mergecost")
368                {
369                        StrX attrValue(attributes.getValue(i));
370                       
371                        const char *ptr = attrValue.LocalForm();
372                        char *endptr = NULL;
373                        const float cost = (float)strtod(ptr, &endptr);
374
375                        viewCell->SetMergeCost(cost);
376                }
377        }
378}
379
380
381void ViewCellsParseHandlers::StartViewSpaceBox(AttributeList& attributes)
382{
383        int len = attributes.getLength();
384
385        Vector3 bmin, bmax;
386
387        for (int i = 0; i < len; ++ i)
388        {
389                string attrName(StrX(attributes.getName(i)).LocalForm());
390                StrX attrValue(attributes.getValue(i));
391                const char *ptr = attrValue.LocalForm();
392
393                if (attrName == "min")
394                {
395                        sscanf(ptr, "%f %f %f",
396                                   &bmin.x, &bmin.y, &bmin.z);
397                }
398                else if (attrName == "max")
399                {
400                        sscanf(ptr, "%f %f %f",
401                                   &bmax.x, &bmax.y, &bmax.z);
402                }
403        }
404
405        mViewSpaceBox = AxisAlignedBox3(bmin, bmax);
406
407        Debug << "\nview space box: " << mViewSpaceBox << endl;
408}
409
410
411void ViewCellsParseHandlers::StartBoundingBox(AttributeList& attributes)
412{
413        int len = attributes.getLength();
414
415        Vector3 bmin, bmax;
416        int id;
417
418        for (int i = 0; i < len; ++ i)
419        {
420                string attrName(StrX(attributes.getName(i)).LocalForm());
421                StrX attrValue(attributes.getValue(i));
422                const char *ptr = attrValue.LocalForm();
423
424
425                if (attrName == "id")
426                {
427                        sscanf(ptr, "%d", &id);
428                }
429
430                if (attrName == "min")
431                {
432                        sscanf(ptr, "%f %f %f",
433                                   &bmin.x, &bmin.y, &bmin.z);
434                }
435                else if (attrName == "max")
436                {
437                        sscanf(ptr, "%f %f %f",
438                                   &bmax.x, &bmax.y, &bmax.z);
439                }
440        }
441
442        AxisAlignedBox3 box(bmin, bmax);
443        mIBoundingBoxes.push_back(IndexedBoundingBox(id, box));
444
445        //Debug << "bbox: " << box << endl;
446}
447
448
449void ViewCellsParseHandlers::StartBspLeaf(AttributeList& attributes)
450{
451        BspLeaf * leaf =
452                new BspLeaf(dynamic_cast<BspInterior *>(mCurrentBspNode), NULL);
453
454        if (mCurrentBspNode) // replace front or (if not NULL) back child
455        {
456                dynamic_cast<BspInterior *>(mCurrentBspNode)->ReplaceChildLink(NULL, leaf);
457        }
458        else
459        {
460                if (mViewCellsManager->GetType() == ViewCellsManager::BSP)
461                {
462                        mBspTree->mRoot = leaf;
463                }
464                else if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP)
465                {
466                        mVspBspTree->mRoot = leaf;
467                }
468        }
469
470        //-- find associated view cell
471        int viewCellId;
472       
473        int len = attributes.getLength();
474         
475        for (int i = 0; i < len; ++ i)
476        {
477                string attrName(StrX(attributes.getName(i)).LocalForm());
478                StrX attrValue(attributes.getValue(i));
479
480                const char *ptr = attrValue.LocalForm();
481                char *endptr = NULL;
482
483                if (attrName == "viewCellId")
484                {
485                        viewCellId = strtol(ptr, &endptr, 10);
486                }
487        }
488
489       
490        if (viewCellId >= 0) // valid view cell
491        {
492                // TODO: get view cell with specified id
493                ViewCellInterior dummyVc;
494                dummyVc.SetId(viewCellId);
495
496                ViewCellContainer::iterator vit =
497                        lower_bound(mViewCells.begin(), mViewCells.end(), &dummyVc, vlt);
498                       
499                BspViewCell *viewCell = dynamic_cast<BspViewCell *>(*vit);
500
501       
502                if (viewCell->GetId() == viewCellId)
503                {
504                        leaf->SetViewCell(viewCell);
505                        viewCell->mLeaf = leaf;
506                }
507                else
508                {
509                        Debug << "error: view cell does not exist" << endl;
510                }
511        }
512        else
513        {
514                // add to invalid view space
515                if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP)
516                {
517                        leaf->SetViewCell(mVspBspTree->GetOrCreateOutOfBoundsCell());
518                        leaf->SetTreeValid(false);
519                        mVspBspTree->PropagateUpValidity(leaf);
520                }
521        }
522}
523
524
525void ViewCellsParseHandlers::StartBspInterior(AttributeList& attributes)
526{
527        Plane3 plane;
528        int len = attributes.getLength();
529
530        for (int i = 0; i < len; ++ i)
531        {
532                string attrName(StrX(attributes.getName(i)).LocalForm());
533                StrX attrValue(attributes.getValue(i));
534                const char *ptr = attrValue.LocalForm();
535
536                if (attrName == "plane")
537                {
538                        sscanf(ptr, "%f %f %f %f",
539                                   &plane.mNormal.x, &plane.mNormal.y, &plane.mNormal.z, &plane.mD);
540                }
541        }
542
543        BspInterior* interior = new BspInterior(plane);
544       
545        if (mCurrentBspNode) // replace NULL child of parent with current node
546        {
547                BspInterior *current = dynamic_cast<BspInterior *>(mCurrentBspNode);
548
549                current->ReplaceChildLink(NULL, interior);
550                interior->SetParent(current);
551        }
552        else
553        {
554                if (mViewCellsManager->GetType() == ViewCellsManager::BSP)
555                {
556                        mBspTree->mRoot = interior;
557                }
558                else
559                {
560                        mVspBspTree->mRoot = interior;
561                }
562        }
563
564        mCurrentBspNode = interior;
565}
566
567
568void ViewCellsParseHandlers::StartViewCellLeaf(AttributeList& attributes)
569{
570        BspViewCell *viewCell = new BspViewCell();
571
572        if (mCurrentViewCell) // replace front or (if not NULL) back child
573        {
574                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(mCurrentViewCell);
575                interior->SetupChildLink(viewCell);
576        }
577        else // root
578        {
579                mViewCellsTree->SetRoot(viewCell);
580        }
581
582        StartViewCell(viewCell, attributes);
583
584        // collect leaves
585        mViewCells.push_back(viewCell);
586}
587
588
589void ViewCellsParseHandlers::StartViewCellInterior(AttributeList& attributes)
590{
591        ViewCellInterior* interior = new ViewCellInterior();
592       
593        if (mCurrentViewCell) // replace NULL child of parent with current node
594        {
595                ViewCellInterior *current = dynamic_cast<ViewCellInterior *>(mCurrentViewCell);
596
597                current->SetupChildLink(interior);
598        }
599        else
600        {
601                mViewCellsTree->SetRoot(interior);
602        }
603
604        mCurrentViewCell = interior;
605
606        StartViewCell(interior, attributes);
607}
608
609
610
611void ViewCellsParseHandlers::CreateViewCellsManager(const char *name)
612{
613        if (strcmp(name, "bspTree") == 0)
614        {
615                Debug << "view cell type: Bsp" << endl;
616
617                mBspTree = new BspTree();
618                mBspTree->mBox = mViewSpaceBox;
619                //mCurrentBspNode = mBspTree->GetRoot();
620
621                mViewCellsManager = new BspViewCellsManager(mBspTree);
622        }
623        else // vspBspTree
624        {
625                Debug << "view cell type: VspBsp" << endl;
626
627                mVspBspTree = new VspBspTree();
628                //mCurrentBspNode = mVspBspTree->GetRoot();
629                mViewCellsManager = new VspBspViewCellsManager(mVspBspTree);
630
631                mVspBspTree->mBox = mViewSpaceBox;
632        }
633
634        mViewCellsTree = mViewCellsManager->GetViewCellsTree();
635        mViewCellsManager->SetViewSpaceBox(mViewSpaceBox);
636}
637
638
639void ViewCellsParseHandlers::characters(const XMLCh* const chars,
640                                                                                const unsigned int length)
641{
642        mCharacterCount += length;
643}
644
645
646void ViewCellsParseHandlers::ignorableWhitespace(const XMLCh* const chars,
647                                                                                                 const unsigned int length)
648{
649        mSpaceCount += length;
650}
651
652
653void ViewCellsParseHandlers::resetDocument()
654{
655        mAttrCount = 0;
656        mCharacterCount = 0;
657        mElementCount = 0;
658        mSpaceCount = 0;
659}
660
661
662// ---------------------------------------------------------------------------
663//  StdInParseHandlers: Overrides of the SAX ErrorHandler interface
664// ---------------------------------------------------------------------------
665void
666ViewCellsParseHandlers::error(const SAXParseException& e)
667{
668  XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId())
669                            << ", line " << e.getLineNumber()
670                            << ", char " << e.getColumnNumber()
671                            << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
672}
673
674void
675ViewCellsParseHandlers::fatalError(const SAXParseException& e)
676{
677  XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId())
678                            << ", line " << e.getLineNumber()
679                            << ", char " << e.getColumnNumber()
680                            << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
681}
682
683void
684ViewCellsParseHandlers::warning(const SAXParseException& e)
685{
686  XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId())
687                            << ", line " << e.getLineNumber()
688                            << ", char " << e.getColumnNumber()
689                            << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
690}
691
692
693bool ViewCellsParser::ParseFile(const string filename,
694                                                                ViewCellsManager **viewCells,
695                                                                ObjectContainer *objects,
696                                                                BoundingBoxConverter *bconverter)
697{
698  // Initialize the XML4C system
699  try {
700    XMLPlatformUtils::Initialize();
701  }
702 
703  catch (const XMLException& toCatch)
704    {
705      XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
706                                << StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
707      return false;
708    }
709 
710  //
711  //  Create a SAX parser object. Then, according to what we were told on
712  //  the command line, set the options.
713  //
714  SAXParser* parser = new SAXParser;
715  parser->setValidationScheme(valScheme);
716  parser->setDoNamespaces(doNamespaces);
717  parser->setDoSchema(doSchema);
718  parser->setValidationSchemaFullChecking(schemaFullChecking);
719 
720
721  //
722  //  Create our SAX handler object and install it on the parser, as the
723  //  document and error handler. We are responsible for cleaning them
724  //  up, but since its just stack based here, there's nothing special
725  //  to do.
726  //
727  ViewCellsParseHandlers handler(objects, bconverter);
728  parser->setDocumentHandler(&handler);
729  parser->setErrorHandler(&handler);
730 
731  unsigned long duration;
732  int errorCount = 0;
733  // create a faux scope so that 'src' destructor is called before
734  // XMLPlatformUtils::Terminate
735  {
736    //
737    //  Kick off the parse and catch any exceptions. Create a standard
738    //  input input source and tell the parser to parse from that.
739    //
740    //    StdInInputSource src;
741    try
742      {
743        const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
744#if ZIPPED_VIEWCELLS
745        XMLCh *myFilePath = XMLString::transcode(filename.c_str());
746       
747        GzFileInputSource isource(myFilePath);
748        parser->parse(isource);
749
750#else
751        parser->parse(filename.c_str());
752#endif
753
754        const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
755        duration = endMillis - startMillis;
756        errorCount = parser->getErrorCount();
757      }
758    catch (const OutOfMemoryException&)
759      {
760        XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
761        errorCount = 2;
762        return false;
763      }
764    catch (const XMLException& e)
765      {
766                        XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
767                                  << StrX(e.getMessage())
768                                  << "\n" << XERCES_STD_QUALIFIER endl;
769                        errorCount = 1;
770                        return false;
771      }
772
773   
774    // Print out the stats that we collected and time taken
775    if (!errorCount) {
776                XERCES_STD_QUALIFIER cerr << filename << ": " << duration << " ms ("
777                                << handler.GetElementCount() << " elems, "
778                                << handler.GetAttrCount() << " attrs, "
779                                << handler.GetSpaceCount() << " spaces, "
780                                << handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
781    }
782  }
783 
784  //
785  //  Delete the parser itself.  Must be done prior to calling Terminate, below.
786  //
787  delete parser;
788 
789  XMLPlatformUtils::Terminate();
790 
791  //-- assign new view cells manager
792  *viewCells = handler.mViewCellsManager;
793 
794  if (errorCount > 0)
795    return false;
796  else
797    return true;
798}
799
800}
Note: See TracBrowser for help on using the repository browser.