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

Revision 2113, 37.3 KB checked in by mattausch, 17 years ago (diff)

warning: debug version

Line 
1// ---------------------------------------------------------------------------
2//  Includes for all the program files to see
3// ---------------------------------------------------------------------------
4#include <string.h>
5#include <stdlib.h>
6#include <iostream>
7//#include <ext/algorithm>
8
9using namespace std;
10#include <xercesc/util/PlatformUtils.hpp>
11
12// ---------------------------------------------------------------------------
13//  Includes
14// ---------------------------------------------------------------------------
15#include <xercesc/framework/StdInInputSource.hpp>
16#include <xercesc/parsers/SAXParser.hpp>
17#include <xercesc/util/OutOfMemoryException.hpp>
18
19// ---------------------------------------------------------------------------
20//  Includes
21// ---------------------------------------------------------------------------
22#include <xercesc/sax/AttributeList.hpp>
23#include <xercesc/sax/SAXParseException.hpp>
24#include <xercesc/sax/SAXException.hpp>
25
26#include "ViewCellsParser.h"
27
28#include "ViewCellsParserXerces.h"
29#include "Mesh.h"
30#include "VspBspTree.h"
31#include "ViewCellBsp.h"
32#include "ViewCellsManager.h"
33#include "GzFileInputSource.h"
34#include "OspTree.h"
35#include "VspTree.h"
36#include "KdTree.h"
37#include "BvHierarchy.h"
38#include "HierarchyManager.h"
39
40
41namespace GtpVisibilityPreprocessor {
42
43
44// ---------------------------------------------------------------------------
45//  Local data
46//
47//  doNamespaces
48//      Indicates whether namespace processing should be enabled or not.
49//      The default is no, but -n overrides that.
50//
51//  doSchema
52//      Indicates whether schema processing should be enabled or not.
53//      The default is no, but -s overrides that.
54//
55//  schemaFullChecking
56//      Indicates whether full schema constraint checking should be enabled or not.
57//      The default is no, but -s overrides that.
58//
59//  valScheme
60//      Indicates what validation scheme to use. It defaults to 'auto', but
61//      can be set via the -v= command.
62// ---------------------------------------------------------------------------
63static bool     doNamespaces       = false;
64static bool     doSchema           = false;
65static bool     schemaFullChecking = false;
66static SAXParser::ValSchemes    valScheme       = SAXParser::Val_Auto;
67
68// hack for loading bvh nodes
69#define PVS_HACK 0
70
71inline static bool ilt(Intersectable *obj1, Intersectable *obj2)
72{
73        return obj1->mId < obj2->mId;
74}
75
76
77// ---------------------------------------------------------------------------
78//  StdInParseHandlers: Constructors and Destructor
79// ---------------------------------------------------------------------------
80ViewCellsParseHandlers::ViewCellsParseHandlers(ObjectContainer &pvsObjects,
81                                                                                           ObjectContainer &preprocessorObjects,
82                                                                                           BoundingBoxConverter *bconverter
83                                                                                           ):
84  mElementCount(0)
85  , mAttrCount(0)
86  , mCharacterCount(0)
87  , mSpaceCount(0)
88  , mViewCellsManager(NULL)
89  , mVspBspTree(NULL)
90  , mBspTree(NULL)
91  , mViewCellsTree(NULL)
92  , mCurrentState(PARSE_OPTIONS)
93  , mCurrentViewCell(NULL)
94  , mCurrentBspNode(NULL)
95  , mCurrentVspNode(NULL)
96  , mCurrentOspNode(NULL)
97  , mCurrentBvhNode(NULL)
98  , mPvsObjects(pvsObjects)
99  , mPreprocessorObjects(preprocessorObjects)
100  , mBoundingBoxConverter(bconverter)
101  , mHierarchyManager(NULL)
102  , nViewCells(0)
103  , nObjects(0)
104{
105        mCreatePvsObjects = mPvsObjects.empty();
106
107        // sort objects so we can search in them
108        //if (!is_sorted(mPvsObjects.begin(), mPvsObjects.end(), ilt))
109                sort(mPvsObjects.begin(), mPvsObjects.end(), ilt);
110
111        //if (!is_sorted(mPreprocessorObjects.begin(), mPreprocessorObjects.end(), ilt))
112                sort(mPreprocessorObjects.begin(), mPreprocessorObjects.end(), ilt);
113}
114
115
116ViewCellsParseHandlers::~ViewCellsParseHandlers()
117{
118}
119
120
121// ---------------------------------------------------------------------------
122//  StdInParseHandlers: Implementation of the SAX DocumentHandler interface
123// ---------------------------------------------------------------------------
124
125
126void ViewCellsParseHandlers::endElement(const XMLCh* const name)
127{
128        StrX lname(name);
129        string element(lname.LocalForm());
130
131        if (element == "BoundingBoxes")
132        {
133                EndBoundingBoxes();
134        }
135
136        if (element == "ViewCells")
137        {       
138                EndViewCells();
139        }
140
141        if (element == "ObjectSpaceHierarchy")
142        {
143                EndObjectSpaceHierarchy();
144        }
145
146        // finished, create view cells manager
147        if (element == "VisibilitySolution")
148        {
149                CreateViewCellsManager();
150        }
151
152        if (element == "Interior")
153        {
154                switch (mCurrentState)
155                {
156                case PARSE_VIEWCELLS:
157                        EndViewCellInterior();
158                        break;
159                case PARSE_OBJECTSPACE_HIERARCHY:
160                        EndObjectSpaceHierarchyInterior();
161                        break;
162                case PARSE_VIEWSPACE_HIERARCHY:
163                        EndViewSpaceHierarchyInterior();
164                        break;
165                default:
166                        break;
167                }
168        }
169}
170
171
172void ViewCellsParseHandlers::EndObjectSpaceHierarchy()
173{
174        if (mObjectSpaceHierarchyType == OSP)
175        {
176                // for a spatial subdivision, it is not necessary to store
177                // the objects with the leaves, they can be classified geometrically
178                mHierarchyManager->mOspTree->
179                        InsertObjects(mHierarchyManager->mOspTree->mRoot, mPvsObjects);
180        }
181}
182
183
184void ViewCellsParseHandlers::EndViewSpaceHierarchyInterior()
185{
186        switch (mViewSpaceHierarchyType)
187        {
188        case BSP:
189                EndBspInterior();
190                break;
191        case VSP:
192                EndVspInterior();
193                break; 
194        default:
195                Debug << "not implemented view space hierarchy type " << mViewSpaceHierarchyType << endl;
196                break;
197        }
198}
199
200
201void ViewCellsParseHandlers::EndObjectSpaceHierarchyInterior()
202{
203        switch (mObjectSpaceHierarchyType)
204        {
205        case OSP:
206                EndOspInterior();
207                break;
208        case BVH:
209                EndBvhInterior();
210                break; 
211        default:
212                Debug << "not implemented object space hierarchy type " << mViewSpaceHierarchyType << endl;
213                break;
214        }
215}
216
217
218void ViewCellsParseHandlers::EndBspInterior()
219{
220        // go one up in the tree
221        if (mCurrentBspNode->GetParent())
222        {       //cout << "]";
223                mCurrentBspNode = mCurrentBspNode->GetParent();
224        }
225}
226
227
228void ViewCellsParseHandlers::EndBvhInterior()
229{
230        // go one up in the tree
231        if (mCurrentBvhNode->GetParent())
232        {       //cout << "]";
233                mCurrentBvhNode = mCurrentBvhNode->GetParent();
234        }
235}
236
237
238void ViewCellsParseHandlers::EndOspInterior()
239{
240        // go one up in the tree
241        if (mCurrentOspNode->mParent)
242        {       
243                //cout << "]";
244                mCurrentOspNode = mCurrentOspNode->mParent;
245        }
246}
247
248
249void ViewCellsParseHandlers::EndVspInterior()
250{
251        // go one up in the tree
252        if (mCurrentVspNode->GetParent())
253        {       
254                //cout << "]";
255                mCurrentVspNode = mCurrentVspNode->GetParent();
256        }
257}
258
259
260void ViewCellsParseHandlers::EndViewCellInterior()
261{
262        // go one up in the tree
263        if (mCurrentViewCell->GetParent())
264        {       
265                //cout << "]";
266                mCurrentViewCell = mCurrentViewCell->GetParent();
267        }
268}
269
270
271inline static bool vlt(ViewCell *v1, ViewCell *v2)
272{
273        return v1->mId < v2->mId;
274}
275
276
277void ViewCellsParseHandlers::EndViewCells()
278{
279        // sort view cells to help associating view cells according to their id
280        stable_sort(mViewCells.begin(), mViewCells.end(), vlt);
281
282        // not parsing view cells anymore
283        mCurrentState = PARSE_OPTIONS;
284}
285
286
287void ViewCellsParseHandlers::EndBoundingBoxes()
288{
289        // all bounding boxes gathered in this step =>
290        // associate object ids with bounding boxes
291        const long startTime = GetTime();
292       
293        if (mBoundingBoxConverter)
294        {
295                mBoundingBoxConverter->IdentifyObjects(mIBoundingBoxes, mPvsObjects);
296        }
297
298        Debug << "\nconverted bounding boxes to objects in "
299                  << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
300}
301
302
303void ViewCellsParseHandlers::StartBspElement(string element,
304                                                                                         AttributeList& attributes)
305{
306        if (element == "Interior")
307        {
308                //cout << "[";
309                StartBspInterior(attributes);
310        }
311
312        if (element == "Leaf")
313        {
314                //cout << "l";
315                StartBspLeaf(attributes);
316        }
317}
318
319
320void ViewCellsParseHandlers::StartVspElement(string element,
321                                                                                         AttributeList& attributes)
322{
323        if (element == "Interior")
324        {
325                //cout << "[";
326                StartVspInterior(attributes);
327        }
328        if (element == "Leaf")
329        {
330                //cout << "l";
331                StartVspLeaf(attributes);
332        }
333}
334
335
336void ViewCellsParseHandlers::StartOspElement(string element,
337                                                                                         AttributeList& attributes)
338{
339        if (element == "Interior")
340        {
341                //cout << "[";
342                StartOspInterior(attributes);
343        }
344
345        if (element == "Leaf")
346        {
347                //cout << "l";
348                StartOspLeaf(attributes);
349        }
350}
351
352
353void ViewCellsParseHandlers::StartBvhElement(string element,
354                                                                                         AttributeList& attributes)
355{
356        if (element == "Interior")
357        {
358                //cout << "[";
359                StartBvhInterior(attributes);
360        }
361
362        if (element == "Leaf")
363        {
364                //cout << "l";
365                StartBvhLeaf(attributes);
366        }
367}
368
369
370void ViewCellsParseHandlers::StartViewSpaceHierarchyElement(const std::string &element,
371                                                                                                                        AttributeList& attributes)
372{
373        //-- use cell type according to the chosen method
374        switch (mViewSpaceHierarchyType)
375        {
376        case BSP:
377                StartBspElement(element, attributes);
378                break;
379        case VSP:
380                StartVspElement(element, attributes);
381                break;
382        default:
383                Debug << "not implemented" << endl;
384                break;
385        }
386}
387
388
389void ViewCellsParseHandlers::StartObjectSpaceHierarchyElement(const std::string &element,
390                                                                                                                          AttributeList& attributes)
391{
392        //-- use cell type according to the chosen method
393        switch (mObjectSpaceHierarchyType)
394        {
395                case OSP:
396                        StartOspElement(element, attributes);
397                        break;
398                case BVH:
399                        StartBvhElement(element, attributes);
400                        break;
401                default:
402                        Debug << "not implemented" << endl;
403                        break;
404        }
405}
406
407
408void ViewCellsParseHandlers::ReplaceBvhPvs(ViewCell *vc)
409{
410        //cout << "exchanging pvs" << endl;
411        ObjectPvs newPvs;
412
413        ObjectPvsIterator pit = vc->GetPvs().GetIterator();
414
415        BvhLeaf *dummyInst = new BvhLeaf(AxisAlignedBox3());
416
417        ObjectContainer oldIntersectables;
418
419        // output PVS of view cell
420        while (pit.HasMoreEntries())
421        {               
422                ObjectPvsEntry entry = pit.Next();
423
424                Intersectable *intersect = entry.mObject;
425                oldIntersectables.push_back(intersect);
426
427                DummyIntersectable *dummyIntersect = static_cast<DummyIntersectable *>(intersect);
428
429                const int objId = dummyIntersect->GetItem();   
430                dummyInst->SetId(objId);
431
432                vector<BvhLeaf *>::iterator oit =
433                        lower_bound(mBvhLeaves.begin(),
434                                                mBvhLeaves.end(),
435                                                dummyInst, ilt);       
436
437                if ((oit != mBvhLeaves.end()) && ((*oit)->GetId() == objId))
438                {
439                        // $$JB we should store a float a per object which corresponds
440                        // to sumof pdfs, i.e. its relative visibility
441                        // temporarily set to 1.0f
442                        //cout << (*oit)->GetId() << " ";
443                       
444                        newPvs.AddSample(*oit, 1.0f);
445                }
446                else
447                {
448                        Debug << "exchangePvs error: object with id " << objId << " does not exist" << endl;
449                }
450        }
451
452        //newPvs.SimpleSort();
453        delete dummyInst;
454        vc->SetPvs(newPvs);
455
456        CLEAR_CONTAINER(oldIntersectables);
457}
458
459
460void ViewCellsParseHandlers::ExchangeElements()
461{
462        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
463       
464        sort(mBvhLeaves.begin(), mBvhLeaves.end(), ilt);
465
466        //cout << "viewcells : " << mViewCells.size() << endl;
467        for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
468        {
469                ReplaceBvhPvs(*vit);
470        }
471}
472
473
474void ViewCellsParseHandlers::StartViewCellHierarchyElement(const std::string &element,
475                                                                                                                   AttributeList& attributes)
476{
477        // interiors + leaves interpreted view cells else
478        if (element == "Interior")
479        {
480                //cout << "[";
481                StartViewCell(attributes, false);
482        }
483
484        if (element == "Leaf")
485        {
486                //cout << "l";
487                StartViewCell(attributes, true);
488        }
489}
490
491
492void ViewCellsParseHandlers::startElement(const XMLCh* const name,
493                                                                                  AttributeList& attributes)
494{
495        StrX lname(name);
496        string element(lname.LocalForm());
497
498        if (element == "ViewCells")
499        {
500                cout << "\nparsing view cells" << endl;
501                Debug << "\nparsing view cells" << endl;
502               
503                mCurrentState = PARSE_VIEWCELLS;
504
505                // create new view cells hierarchy
506                mViewCellsTree = new ViewCellsTree();
507        }
508
509        // decides about the view cell hierarchy
510        if (element == "ViewSpaceHierarchy")
511        {               
512                Debug << "\nparsing view space hierarchy" << endl;
513                cout << "\nparsing view space hierarchy" << endl;
514                mCurrentState = PARSE_VIEWSPACE_HIERARCHY;
515                StartViewSpaceHierarchy(attributes);
516        }
517
518        // decides about the view cell hierarchy
519        if (element == "ObjectSpaceHierarchy")
520        {
521                cout << "\nparsing object space hierarchy" << endl;
522                Debug << "\nparsing object space hierarchy" << endl;
523
524                mCurrentState = PARSE_OBJECTSPACE_HIERARCHY;
525                StartObjectSpaceHierarchy(attributes);
526        }
527       
528        // decides the used view cell hierarchy
529        if (element == "BoundingBox")
530        {
531                // cout << "b";
532                StartBoundingBox(attributes);
533        }
534
535        // parse view space hierarchy
536        switch (mCurrentState)
537        {
538        case PARSE_VIEWSPACE_HIERARCHY:
539                if ((++ nViewCells % 1000) == 0)
540                        cout<<"\r"<<nViewCells<<" view cells parsed\r";
541               
542                StartViewSpaceHierarchyElement(element, attributes);
543                break;
544        case PARSE_OBJECTSPACE_HIERARCHY:
545                if ((++ nObjects % 1000) == 0)
546                 cout<<"\r"<< nObjects <<" objects parsed\r";
547               
548                StartObjectSpaceHierarchyElement(element, attributes);
549                break;
550        case PARSE_VIEWCELLS:
551                StartViewCellHierarchyElement(element, attributes);
552                break;
553        default:
554                break;
555        }
556       
557        ++ mElementCount;
558        mAttrCount += attributes.getLength();
559}
560
561
562void ViewCellsParseHandlers::StartViewCellPvs(ObjectPvs &pvs, const char *ptr)
563{
564        // handle obect indices
565        vector<int> objIndices;
566        char *endptr;
567                       
568        while (1)
569        {       // read object ids
570                const int index = strtol(ptr, &endptr, 10);
571                if (ptr == endptr)
572                        break;
573                objIndices.push_back(index);
574                ptr = endptr;
575        }
576
577        // TODO:
578        // 1) find objects and add them to pvs
579        // 2) get view cell with specified id
580        MeshInstance dummyInst(NULL);
581
582        vector<int>::const_iterator it, it_end = objIndices.end();
583        for (it = objIndices.begin(); it != it_end; ++ it)
584        {
585#if PVS_HACK
586                //cout << "u";
587                pvs.AddSample(new DummyIntersectable(*it), 1);
588#else
589                const int objId = *it; 
590                dummyInst.SetId(objId);
591
592                ObjectContainer::iterator oit =
593                                                                lower_bound(mPvsObjects.begin(),
594                                                                                        mPvsObjects.end(),
595                                                                                        (Intersectable *)&dummyInst, ilt);     
596
597                if ((oit != mPvsObjects.end()) && ((*oit)->GetId() == objId))
598                {
599                        // $$JB we should store a float a per object which corresponds
600                        // to sumof pdfs, i.e. its relative visibility
601                        // temporarily set to 1.0f
602                        pvs.AddSample(*oit, 1.0f);
603                        //Debug << "y";
604                }
605                else
606                {
607                        Debug << "x";
608                        //Debug << "StartViewCellPvs error: object with id " << objId << " does not exist" << endl;
609                }
610#endif
611        }
612}
613
614
615void ViewCellsParseHandlers::StartViewSpaceHierarchy(AttributeList& attributes)
616{
617        int len = attributes.getLength();
618
619        Vector3 bmin, bmax;
620
621        for (int i = 0; i < len; ++ i)
622        {
623                string attrName(StrX(attributes.getName(i)).LocalForm());
624                StrX attrValue(attributes.getValue(i));
625                const char *ptr = attrValue.LocalForm();
626
627                // hierarchy type
628                if (attrName == "type")
629                {
630                        if (strcmp(ptr, "bsp") == 0)
631                        {
632                                Debug << "\nview space hierarchy: Bsp" << endl;
633                                mViewSpaceHierarchyType = BSP;
634                        }
635                        else if (strcmp(ptr, "vsp") == 0)
636                        {
637                                Debug << "\nview space hierarchy: Vsp" << endl;
638                                mViewSpaceHierarchyType = VSP;
639                        }
640                }
641                else if (attrName == "min") // the view space extent
642                {
643                        sscanf(ptr, "%f %f %f",
644                                   &bmin.x, &bmin.y, &bmin.z);
645                }
646                else if (attrName == "max")
647                {
648                        sscanf(ptr, "%f %f %f",
649                                   &bmax.x, &bmax.y, &bmax.z);
650                }
651        }
652
653        mViewSpaceBox = AxisAlignedBox3(bmin, bmax);
654
655        // create the hierarchy based on this information
656        CreateViewSpaceHierarchy();
657}
658
659
660void ViewCellsParseHandlers::StartObjectSpaceHierarchy(AttributeList& attributes)
661{
662        const int len = attributes.getLength();
663        Vector3 bmin, bmax;
664
665        for (int i = 0; i < len; ++ i)
666        {
667                string attrName(StrX(attributes.getName(i)).LocalForm());
668                StrX attrValue(attributes.getValue(i));
669                const char *ptr = attrValue.LocalForm();
670
671                // hierarchy type
672                if (attrName == "type")
673                {
674                        if (strcmp(ptr, "osp") == 0)
675                        {
676                                Debug << "\nobject space hierarchy: Osp" << endl;
677
678                                mHierarchyManager =
679                                        new HierarchyManager(HierarchyManager::KD_BASED_OBJ_SUBDIV);
680
681                                DEL_PTR(mHierarchyManager->mVspTree);
682                                mHierarchyManager->mVspTree = mVspTree;
683
684                                mObjectSpaceHierarchyType = OSP;
685
686                                //std::stable_sort(objects.begin(), objects.end(), ilt);
687                                mHierarchyManager->mOspTree->mBoundingBox.Initialize();
688                                ObjectContainer::const_iterator oit, oit_end = mPvsObjects.end();
689                               
690                                //-- compute bounding box
691                                for (oit = mPvsObjects.begin(); oit != oit_end; ++ oit)
692                                {
693                                        Intersectable *obj = *oit;
694                                        // compute bounding box of view space
695                                        mHierarchyManager->mOspTree->mBoundingBox.Include(obj->GetBox());
696                                }
697                        }
698                        else if (strcmp(ptr, "bvh") == 0)
699                        {
700                                Debug << "\nobject space hierarchy: Bvh" << endl;
701                                mObjectSpaceHierarchyType = BVH;
702                                mHierarchyManager =
703                                        new HierarchyManager(HierarchyManager::BV_BASED_OBJ_SUBDIV);
704
705                                DEL_PTR(mHierarchyManager->mVspTree);
706                                mHierarchyManager->mVspTree = mVspTree;
707                        }
708                }
709        }
710}
711
712
713void ViewCellsParseHandlers::StartBoundingBox(AttributeList& attributes)
714{
715        int len = attributes.getLength();
716
717        Vector3 bmin, bmax;
718        int id;
719
720        for (int i = 0; i < len; ++ i)
721        {
722                string attrName(StrX(attributes.getName(i)).LocalForm());
723                StrX attrValue(attributes.getValue(i));
724                const char *ptr = attrValue.LocalForm();
725
726                if (attrName == "id")
727                {
728                        sscanf(ptr, "%d", &id);
729                }
730                if (attrName == "min")
731                {
732                        sscanf(ptr, "%f %f %f", &bmin.x, &bmin.y, &bmin.z);
733                }
734                else if (attrName == "max")
735                {
736                        sscanf(ptr, "%f %f %f", &bmax.x, &bmax.y, &bmax.z);
737                }
738        }
739
740        AxisAlignedBox3 box(bmin, bmax);
741        mIBoundingBoxes.push_back(IndexedBoundingBox(id, box));
742        //Debug << "bbox: " << box << endl;
743}
744
745
746void ViewCellsParseHandlers::StartBspLeaf(AttributeList& attributes)
747{
748        BspLeaf * leaf;
749
750        if (mCurrentBspNode) // replace front or (if not NULL) back child
751        {
752                BspInterior *interior = static_cast<BspInterior *>(mCurrentBspNode);
753
754                leaf = new BspLeaf(interior);
755                interior->ReplaceChildLink(NULL, leaf);
756        }
757        else
758        {
759                leaf = new BspLeaf();
760                mVspBspTree->mRoot = leaf;
761        }
762
763        ///////////
764        //-- find associated view cell
765
766        int viewCellId;
767        const int len = attributes.getLength();
768         
769        for (int i = 0; i < len; ++ i)
770        {
771                string attrName(StrX(attributes.getName(i)).LocalForm());
772                StrX attrValue(attributes.getValue(i));
773
774                const char *ptr = attrValue.LocalForm();
775                char *endptr = NULL;
776
777                if (attrName == "viewCellId")
778                {
779                        viewCellId = strtol(ptr, &endptr, 10);
780                }
781        }
782       
783        if (viewCellId >= 0) // valid view cell found
784        {
785                // TODO: get view cell with specified id
786                ViewCellInterior dummyVc;
787                dummyVc.SetId(viewCellId);
788
789                ViewCellContainer::iterator vit =
790                        lower_bound(mViewCells.begin(), mViewCells.end(), &dummyVc, vlt);
791               
792                //ViewCellsMap::iterator vit = mViewCells.find(viewCellId);
793//              BspViewCell *viewCell = static_cast<BspViewCell *>((*vit).second);
794
795                BspViewCell *viewCell = static_cast<BspViewCell *>(*vit);
796                if (viewCell->GetId() == viewCellId)
797                {
798                        // create new view cell for bsp nodes
799                        leaf->SetViewCell(viewCell);
800                        viewCell->mLeaves.push_back(leaf);
801                }
802                else
803                {
804                        cerr << "error: view cell does not exist" << endl;
805                }
806        }
807        else
808        {
809                // add to invalid view space
810                leaf->SetViewCell(mVspBspTree->GetOrCreateOutOfBoundsCell());
811                leaf->SetTreeValid(false);
812                mVspBspTree->PropagateUpValidity(leaf);
813        }
814}
815
816
817void ViewCellsParseHandlers::StartBspInterior(AttributeList& attributes)
818{
819        Plane3 plane;
820        int len = attributes.getLength();
821
822        for (int i = 0; i < len; ++ i)
823        {
824                string attrName(StrX(attributes.getName(i)).LocalForm());
825                StrX attrValue(attributes.getValue(i));
826                const char *ptr = attrValue.LocalForm();
827
828                if (attrName == "plane")
829                {
830                        sscanf(ptr, "%f %f %f %f",
831                                   &plane.mNormal.x, &plane.mNormal.y, &plane.mNormal.z, &plane.mD);
832                }
833        }
834
835        BspInterior* interior = new BspInterior(plane);
836       
837        if (mCurrentBspNode) // replace NULL child of parent with current node
838        {
839                BspInterior *parent = static_cast<BspInterior *>(mCurrentBspNode);
840
841                parent->ReplaceChildLink(NULL, interior);
842                interior->SetParent(parent);
843        }
844        else
845        {
846                mVspBspTree->mRoot = interior;
847        }
848
849        mCurrentBspNode = interior;
850}
851
852
853void ViewCellsParseHandlers::StartViewCell(AttributeList& attributes, const bool isLeaf)
854{
855        ViewCell *viewCell = NULL;
856       
857        const int len = attributes.getLength();
858        float mergeCost;
859       
860        if (isLeaf)
861        {
862                viewCell = new ViewCellLeaf();
863        }
864        else
865        {
866                viewCell = new ViewCellInterior();
867        }
868
869        for (int i = 0; i < len; ++ i)
870        {
871                const string attrName(StrX(attributes.getName(i)).LocalForm());
872       
873                if (attrName == "id")
874                {
875                        const StrX attrValue(attributes.getValue(i));
876                        const char *ptr = attrValue.LocalForm();
877                        char *endptr = NULL;
878                        const int id = strtol(ptr, &endptr, 10);
879
880                        // create new view cell, otherwise use reference.
881                        viewCell->SetId(id);
882
883                        if (mCurrentViewCell) // replace front or (if not NULL) back child
884                        {       
885                                ViewCellInterior *interior =
886                                        static_cast<ViewCellInterior *>(mCurrentViewCell);
887                                interior->SetupChildLink(viewCell);
888                        }
889                        else
890                        {       // set the new root
891                                mViewCellsTree->SetRoot(viewCell);
892                        }
893                       
894                        if (!isLeaf)
895                        {
896                                mCurrentViewCell = viewCell;
897                        }
898                }
899                if (attrName == "pvs")
900                {
901                        StrX attrValue(attributes.getValue(i));
902                        const char *ptr = attrValue.LocalForm();
903
904                        // note: id must come before pvs!
905                        // otherwise view cell is undefined
906
907                        // hack: assume that view cell comes before pvs
908                        StartViewCellPvs(viewCell->GetPvs(), ptr);
909                        //StartViewCellPvs(pvs, ptr);
910                }
911                else if (attrName == "active")
912                {
913                        StrX attrValue(attributes.getValue(i));
914                        const char *ptr = attrValue.LocalForm();
915                        char *endptr = NULL;
916                        const bool isActive = (bool)strtol(ptr, &endptr, 10);
917
918                        if (isActive)
919                        {
920                                // TODO
921                        }
922                }
923                else if (attrName == "mergecost")
924                {
925                        StrX attrValue(attributes.getValue(i));
926                       
927                        const char *ptr = attrValue.LocalForm();
928                        char *endptr = NULL;
929                        mergeCost = (float)strtod(ptr, &endptr);
930                }
931        }
932
933        viewCell->SetMergeCost(mergeCost);
934        //viewCell->SetPvs(pvs);
935        mViewCells.push_back(viewCell);
936}
937
938
939void ViewCellsParseHandlers::CreateViewSpaceHierarchy()
940{
941        if (mViewSpaceHierarchyType == BSP)
942        {
943                Debug << "hierarchy type: Bsp" << endl;
944                mVspBspTree = new VspBspTree();
945
946                // set view space box
947                mVspBspTree->mBoundingBox = mViewSpaceBox;
948
949                //ViewCellsMap::iterator vit, vit_end = mViewCells.end();
950                ViewCellContainer::iterator vit, vit_end = mViewCells.end();
951
952                int i = 0;
953                // remove view cells and exchange them with the
954                // view cells specialized for the current hierarchy node type
955                for (vit = mViewCells.begin(); vit != vit_end; ++ vit, ++ i)
956                {
957                        //if ((i % 1000) == 0)
958                        //      Debug << "\n exchanged " << i << " boxes" << endl;
959                        ViewCell *vc = (*vit);
960
961                        if (!vc->IsLeaf()) // exchange only leaves
962                                continue;
963               
964                        BspViewCell *bspVc = new BspViewCell();
965
966                        bspVc->SetId(vc->GetId());
967                        //bspVc->GetPvs().reserve(vc->GetPvs().size());
968                        bspVc->SetPvs(vc->GetPvs());
969
970                        if (vc->IsRoot())
971                        {
972                                mViewCellsTree->mRoot = bspVc;
973                        }
974                        else
975                        {
976                vc->GetParent()->ReplaceChildLink(vc, bspVc);
977                        }
978
979                        // delete old view cell
980                        DEL_PTR(vc);
981
982//                      (*vit).second = bspVc;
983                        (*vit) = bspVc;
984                }
985                cout << "finished creating view space hierarchy" << endl;
986        }
987        else if (mViewSpaceHierarchyType == VSP)
988        {
989                Debug << "hierarchy type: Vsp" << endl;
990                mVspTree = new VspTree();
991
992                // set view space box
993                mVspTree->mBoundingBox = mViewSpaceBox;
994
995                // ViewCellsMap::iterator vit, vit_end = mViewCells.end();
996                ViewCellContainer::iterator vit, vit_end = mViewCells.end();
997
998                // reset view cells using the current node type
999                for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
1000                {
1001                        //ViewCell *vc = (*vit).second;
1002                        ViewCell *vc = (*vit);
1003                       
1004                        if (!vc->IsLeaf()) // exchange only leaves
1005                                continue;
1006
1007                        VspViewCell *vspVc = new VspViewCell();
1008
1009                        vspVc->SetPvs(vc->GetPvs());
1010                        vspVc->SetId(vc->GetId());
1011
1012                        if (vc->IsRoot())
1013                        {
1014                                mViewCellsTree->mRoot = vspVc;
1015                        }
1016                        else
1017                        {
1018                                vc->GetParent()->ReplaceChildLink(vc, vspVc);
1019                        }
1020                       
1021                        // exchange view cell with new one
1022                        DEL_PTR(vc);
1023
1024                        //(*vit).second = vspVc;
1025                        (*vit) = vspVc;
1026                }
1027
1028                if (mHierarchyManager)
1029                {
1030                        // come here only if object space hierarchy already constructed
1031                        mHierarchyManager->mVspTree = mVspTree;
1032                        mVspTree->mHierarchyManager = mHierarchyManager;
1033                }
1034        }
1035}
1036
1037
1038void ViewCellsParseHandlers::CreateViewCellsManager()
1039{
1040        if (mViewSpaceHierarchyType == BSP)
1041        {
1042                Debug << "\ncreating view cells manager: VspBsp" << endl;
1043                mViewCellsManager = new VspBspViewCellsManager(mViewCellsTree, mVspBspTree);
1044        }
1045        else if (mViewSpaceHierarchyType == VSP)
1046        {
1047                Debug << "\ncreating view cells manager: VspOsp" << endl;
1048                mViewCellsManager = new VspOspViewCellsManager(mViewCellsTree, mHierarchyManager);
1049        }
1050
1051        mViewCellsManager->SetViewSpaceBox(mViewSpaceBox);
1052}
1053
1054
1055void ViewCellsParseHandlers::characters(const XMLCh* const chars,
1056                                                                                const unsigned int length)
1057{
1058        mCharacterCount += length;
1059}
1060
1061
1062void ViewCellsParseHandlers::ignorableWhitespace(const XMLCh* const chars,
1063                                                                                                 const unsigned int length)
1064{
1065        mSpaceCount += length;
1066}
1067
1068
1069void ViewCellsParseHandlers::resetDocument()
1070{
1071        mAttrCount = 0;
1072        mCharacterCount = 0;
1073        mElementCount = 0;
1074        mSpaceCount = 0;
1075}
1076
1077
1078void ViewCellsParseHandlers::StartVspLeaf(AttributeList& attributes)
1079{
1080        VspLeaf * leaf;
1081               
1082        if (mCurrentVspNode) // replace front or (if not NULL) back child
1083        {
1084                VspInterior *interior = static_cast<VspInterior *>(mCurrentVspNode);
1085                leaf = new VspLeaf(interior);
1086                interior->ReplaceChildLink(NULL, leaf);
1087        }
1088        else
1089        {
1090                leaf = new VspLeaf();
1091                mVspTree->mRoot = leaf;
1092        }
1093
1094        /////////////
1095        //-- find view cell associated with the id
1096
1097        int viewCellId;
1098        const int len = attributes.getLength();
1099         
1100        for (int i = 0; i < len; ++ i)
1101        {
1102                string attrName(StrX(attributes.getName(i)).LocalForm());
1103                StrX attrValue(attributes.getValue(i));
1104
1105                const char *ptr = attrValue.LocalForm();
1106                char *endptr = NULL;
1107
1108                if (attrName == "viewCellId")
1109                {
1110                        viewCellId = strtol(ptr, &endptr, 10);
1111                }
1112        }
1113       
1114        if (viewCellId >= 0) // valid view cell found
1115        {
1116                // TODO: get view cell with specified id
1117                ViewCellInterior dummyVc;
1118                dummyVc.SetId(viewCellId);
1119
1120                ViewCellContainer::iterator vit =
1121                        lower_bound(mViewCells.begin(), mViewCells.end(), &dummyVc, vlt);
1122               
1123                //ViewCellsMap::iterator vit = mViewCells.find(viewCellId);
1124                if (vit == mViewCells.end())
1125                        Debug << "error: view cell " << viewCellId << " not found" << endl;
1126       
1127                //VspViewCell *viewCell = static_cast<VspViewCell *>((*vit).second);
1128                VspViewCell *viewCell = static_cast<VspViewCell *>(*vit);
1129               
1130                if (viewCell->GetId() == viewCellId)
1131                {
1132                        leaf->SetViewCell(viewCell);
1133                        viewCell->mLeaves.push_back(leaf);
1134                }
1135                else
1136                {
1137                        Debug << "error: view cell does not exist" << endl;
1138                }
1139        }
1140        else
1141        {       
1142                // add to invalid view space
1143                leaf->SetViewCell(mVspTree->GetOrCreateOutOfBoundsCell());
1144                leaf->SetTreeValid(false);
1145                mVspTree->PropagateUpValidity(leaf);
1146        }
1147}
1148
1149
1150void ViewCellsParseHandlers::StartVspInterior(AttributeList& attributes)
1151{
1152        AxisAlignedPlane plane;
1153        const int len = attributes.getLength();
1154
1155        for (int i = 0; i < len; ++ i)
1156        {
1157                string attrName(StrX(attributes.getName(i)).LocalForm());
1158                StrX attrValue(attributes.getValue(i));
1159                const char *ptr = attrValue.LocalForm();
1160
1161                if (attrName == "plane")
1162                {
1163                        sscanf(ptr, "%f %d", &plane.mPosition, &plane.mAxis);
1164                }
1165        }
1166
1167        VspInterior* interior = new VspInterior(plane);
1168       
1169        if (mCurrentVspNode) // replace NULL child of parent with current node
1170        {
1171                VspInterior *parent = static_cast<VspInterior *>(mCurrentVspNode);
1172
1173                parent->ReplaceChildLink(NULL, interior);
1174                interior->SetParent(parent);
1175               
1176                AxisAlignedBox3 frontBox, backBox;
1177
1178                parent->GetBoundingBox().Split(
1179                        parent->GetPlane().mAxis,
1180                        parent->GetPlane().mPosition,
1181                        frontBox,
1182                        backBox);
1183
1184                if (parent->GetFront() == interior)
1185                        interior->SetBoundingBox(frontBox);
1186                else
1187                        interior->SetBoundingBox(backBox);
1188        }
1189        else
1190        {
1191                mVspTree->mRoot = interior;
1192                interior->SetBoundingBox(mVspTree->GetBoundingBox());
1193        }
1194
1195        mCurrentVspNode = interior;
1196}
1197
1198
1199void ViewCellsParseHandlers::StartOspInterior(AttributeList& attributes)
1200{
1201        AxisAlignedPlane plane;
1202        int len = attributes.getLength();
1203
1204        for (int i = 0; i < len; ++ i)
1205        {
1206                string attrName(StrX(attributes.getName(i)).LocalForm());
1207                StrX attrValue(attributes.getValue(i));
1208                const char *ptr = attrValue.LocalForm();
1209
1210                if (attrName == "plane")
1211                {
1212                        sscanf(ptr, "%f %d", &plane.mPosition, &plane.mAxis);
1213                }
1214        }
1215
1216        KdInterior* interior = new KdInterior(NULL);
1217       
1218        interior->mAxis = plane.mAxis;
1219        interior->mPosition = plane.mPosition;
1220
1221        if (mCurrentOspNode) // replace NULL child of parent with current node
1222        {
1223                KdInterior *parent = static_cast<KdInterior *>(mCurrentOspNode);
1224                parent->ReplaceChildLink(NULL, interior);
1225                interior->mParent = parent;
1226
1227                AxisAlignedBox3 frontBox, backBox;
1228
1229                parent->mBox.Split(parent->mAxis, parent->mPosition, frontBox, backBox);
1230
1231                if (parent->mFront == interior)
1232                        interior->mBox = frontBox;
1233                else
1234                        interior->mBox = backBox;
1235        }
1236        else
1237        {
1238                mHierarchyManager->mOspTree->mRoot = interior;
1239                interior->mBox = mHierarchyManager->mOspTree->mBoundingBox;
1240        }
1241
1242        mCurrentOspNode = interior;
1243}
1244
1245
1246void ViewCellsParseHandlers::StartOspLeaf(AttributeList& attributes)
1247{
1248        KdLeaf * leaf = new KdLeaf(static_cast<KdInterior *>(mCurrentOspNode), NULL);
1249
1250        if (mCurrentOspNode)
1251        {
1252                 // replace front or (if not NULL) back child
1253                static_cast<KdInterior *>(mCurrentOspNode)->ReplaceChildLink(NULL, leaf);
1254        }
1255        else
1256        {
1257                mHierarchyManager->mOspTree->mRoot = leaf;
1258        }
1259}
1260
1261
1262void ViewCellsParseHandlers::StartBvhLeaf(AttributeList& attributes)
1263{
1264        const int len = attributes.getLength();
1265        Vector3 minBox, maxBox;
1266
1267        ObjectContainer objects;
1268
1269        for (int i = 0; i < len; ++ i)
1270        {
1271                string attrName(StrX(attributes.getName(i)).LocalForm());
1272                StrX attrValue(attributes.getValue(i));
1273                const char *ptr = attrValue.LocalForm();
1274
1275                if (attrName == "min")
1276                {
1277                        sscanf(ptr, "%f %f %f", &minBox.x, &minBox.y, &minBox.z);
1278                }
1279                if (attrName == "max")
1280                {
1281                        sscanf(ptr, "%f %f %f", &maxBox.x, &maxBox.y, &maxBox.z);
1282                }
1283                if (attrName == "objects")
1284                {
1285                        StartBvhLeafObjects(objects, ptr);
1286                }
1287        }
1288
1289        AxisAlignedBox3 box = AxisAlignedBox3(minBox, maxBox);
1290
1291        BvhLeaf *leaf;
1292
1293        if (mCurrentBvhNode) // replace front or (if not NULL) back child
1294        {
1295                BvhInterior *interior = static_cast<BvhInterior *>(mCurrentBvhNode);
1296                leaf = new BvhLeaf(box, interior, (int)objects.size());
1297                interior->ReplaceChildLink(NULL, leaf);
1298        }
1299        else
1300        {
1301                leaf = new BvhLeaf(box, NULL, (int)objects.size());
1302                mHierarchyManager->mBvHierarchy->mRoot = leaf;
1303        }
1304
1305        leaf->mObjects = objects;
1306        BvHierarchy::AssociateObjectsWithLeaf(leaf);
1307       
1308        if (PVS_HACK)
1309        {
1310                if (0) // Temp matt: should already have right id
1311                        leaf->SetId((int)mBvhLeaves.size());
1312               
1313                mBvhLeaves.push_back(leaf);     
1314        }
1315}
1316
1317
1318void ViewCellsParseHandlers::StartBvhLeafObjects(ObjectContainer &objects,
1319                                                                                                 const char *ptr)
1320{
1321        vector<int> objIndices;
1322        char *endptr;
1323                       
1324        while (1)
1325        {
1326                const int index = strtol(ptr, &endptr, 10);
1327                if (ptr == endptr) break;
1328
1329                objIndices.push_back(index);
1330                ptr = endptr;
1331        }
1332
1333        MeshInstance dummyInst(NULL);
1334
1335        vector<int>::const_iterator it, it_end = objIndices.end();
1336
1337        for (it = objIndices.begin(); it != it_end; ++ it)
1338        {
1339                const int objId = *it; 
1340                dummyInst.SetId(objId);
1341
1342                ObjectContainer::iterator oit =
1343                        lower_bound(mPvsObjects.begin(),
1344                                                mPvsObjects.end(),
1345                                                (Intersectable *)&dummyInst,
1346                                                ilt);   
1347                                                       
1348                if ((oit != mPvsObjects.end()) && ((*oit)->GetId() == objId))
1349                {
1350                        objects.push_back(*oit);
1351                        Debug << "x";
1352                }
1353                else
1354                {
1355                        Debug << "y";
1356                        //cerr << "StartBvhLeafObjects error: object with id " << objId << " does not exist" << endl;
1357                }
1358        }
1359}
1360
1361
1362void ViewCellsParseHandlers::StartBvhInterior(AttributeList& attributes)
1363{
1364        const int len = attributes.getLength();
1365        Vector3 minBox, maxBox;
1366
1367        for (int i = 0; i < len; ++ i)
1368        {
1369                string attrName(StrX(attributes.getName(i)).LocalForm());
1370                StrX attrValue(attributes.getValue(i));
1371                const char *ptr = attrValue.LocalForm();
1372
1373                if (attrName == "min")
1374                {
1375                        sscanf(ptr, "%f %f %f", &minBox.x, &minBox.y, &minBox.z);
1376                }
1377                if (attrName == "max")
1378                {
1379                        sscanf(ptr, "%f %f %f", &maxBox.x, &maxBox.y, &maxBox.z);
1380                }
1381        }
1382
1383        BvhInterior* interior = new BvhInterior(AxisAlignedBox3(minBox, maxBox));
1384
1385        if (mCurrentBvhNode) // replace NULL child of parent with current node
1386        {
1387                BvhInterior *parent = static_cast<BvhInterior *>(mCurrentBvhNode);
1388                parent->ReplaceChildLink(NULL, interior);
1389                interior->SetParent(parent);
1390        }
1391        else
1392        {
1393                mHierarchyManager->mBvHierarchy->mRoot = interior;
1394        }
1395
1396        mCurrentBvhNode = interior;
1397}
1398
1399
1400// ---------------------------------------------------------------------------
1401//  StdInParseHandlers: Overrides of the SAX ErrorHandler interface
1402// ---------------------------------------------------------------------------
1403
1404
1405void
1406ViewCellsParseHandlers::error(const SAXParseException& e)
1407{
1408  XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId())
1409                            << ", line " << e.getLineNumber()
1410                            << ", char " << e.getColumnNumber()
1411                            << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
1412}
1413
1414void
1415ViewCellsParseHandlers::fatalError(const SAXParseException& e)
1416{
1417  XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId())
1418                            << ", line " << e.getLineNumber()
1419                            << ", char " << e.getColumnNumber()
1420                            << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
1421}
1422
1423void
1424ViewCellsParseHandlers::warning(const SAXParseException& e)
1425{
1426  XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId())
1427                            << ", line " << e.getLineNumber()
1428                            << ", char " << e.getColumnNumber()
1429                            << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
1430}
1431
1432
1433bool ViewCellsParser::ParseViewCellsFile(const string &filename,
1434                                                                                 ViewCellsManager **viewCells,
1435                                                                                 ObjectContainer &pvsObjects,
1436                                                                                 ObjectContainer &preprocessorObjects,
1437                                                                                 BoundingBoxConverter *bconverter)
1438{
1439  // Initialize the XML4C system
1440  try {
1441    XMLPlatformUtils::Initialize();
1442  }
1443 
1444  catch (const XMLException& toCatch)
1445    {
1446      XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
1447                                << StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
1448      return false;
1449    }
1450
1451  //  cout<<"parsing started"<<endl<<flush;
1452
1453  //
1454  //  Create a SAX parser object. Then, according to what we were told on
1455  //  the command line, set the options.
1456  //
1457  SAXParser* parser = new SAXParser;
1458  parser->setValidationScheme(valScheme);
1459  parser->setDoNamespaces(doNamespaces);
1460  parser->setDoSchema(doSchema);
1461  parser->setValidationSchemaFullChecking(schemaFullChecking);
1462 
1463
1464  //
1465  //  Create our SAX handler object and install it on the parser, as the
1466  //  document and error handler. We are responsible for cleaning them
1467  //  up, but since its just stack based here, there's nothing special
1468  //  to do.
1469  //
1470  ViewCellsParseHandlers handler(pvsObjects, preprocessorObjects, bconverter);
1471  parser->setDocumentHandler(&handler);
1472  parser->setErrorHandler(&handler);
1473 
1474  unsigned long duration;
1475  int errorCount = 0;
1476  // create a faux scope so that 'src' destructor is called before
1477  // XMLPlatformUtils::Terminate
1478  {
1479    //
1480    //  Kick off the parse and catch any exceptions. Create a standard
1481    //  input input source and tell the parser to parse from that.
1482    //
1483    //    StdInInputSource src;
1484    try
1485        {
1486        const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
1487
1488#if USE_GZLIB
1489        XMLCh *myFilePath = XMLString::transcode(filename.c_str());
1490       
1491        GzFileInputSource isource(myFilePath);
1492        parser->parse(isource);
1493#else
1494        parser->parse(filename.c_str());
1495
1496#endif
1497
1498        if (1 && PVS_HACK)
1499                handler.ExchangeElements();
1500
1501        const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
1502        duration = endMillis - startMillis;
1503        errorCount = parser->getErrorCount();
1504      }
1505    catch (const OutOfMemoryException&)
1506      {
1507        XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
1508        errorCount = 2;
1509        return false;
1510      }
1511    catch (const XMLException& e)
1512      {
1513                        XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
1514                                  << StrX(e.getMessage())
1515                                  << "\n" << XERCES_STD_QUALIFIER endl;
1516                        errorCount = 1;
1517                        return false;
1518      }
1519
1520   
1521    // Print out the stats that we collected and time taken
1522    if (!errorCount) {
1523                XERCES_STD_QUALIFIER cerr << filename << ": " << duration << " ms ("
1524                                << handler.GetElementCount() << " elems, "
1525                                << handler.GetAttrCount() << " attrs, "
1526                                << handler.GetSpaceCount() << " spaces, "
1527                                << handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
1528    }
1529  }
1530
1531  cout<<"parsed - will delete the parser"<<endl<<flush;
1532  //
1533  //  Delete the parser itself.  Must be done prior to calling Terminate, below.
1534  //
1535  delete parser;
1536 
1537  XMLPlatformUtils::Terminate();
1538 
1539  //-- assign new view cells manager
1540  *viewCells = handler.mViewCellsManager;
1541 
1542  if (errorCount > 0)
1543    return false;
1544  else
1545    return true;
1546}
1547
1548}
Note: See TracBrowser for help on using the repository browser.