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

Revision 870, 17.9 KB checked in by mattausch, 18 years ago (diff)

added pvs

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