source: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h @ 2347

Revision 2347, 18.6 KB checked in by mattausch, 17 years ago (diff)

debug version

RevLine 
[1237]1#ifndef _HierarchyManager_H__
2#define _HierarchyManager_H__
3
4#include <stack>
5
6#include "Mesh.h"
7#include "Containers.h"
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11#include "gzstream.h"
[1239]12#include "SubdivisionCandidate.h"
[1237]13
14
15
16namespace GtpVisibilityPreprocessor {
17
18class ViewCellLeaf;
19class OspTree;
20class VspTree;
21class Plane3;
22class AxisAlignedBox3;
23class Ray;
24class ViewCellsStatistics;
25class ViewCellsManager;
26class MergeCandidate;
27class Beam;
28class ViewCellsTree;
29class Environment;
30class VspInterior;
31class VspLeaf;
32class VspNode;
33class KdNode;
34class KdInterior;
35class KdLeaf;
36class OspTree;
37class KdIntersectable;
38class KdTree;
39class VspTree;
40class KdTreeStatistics;
[1259]41class BvHierarchy;
[1287]42class Exporter;
[1667]43class ViewCellsParseHandlers;
[2094]44class TraversalTree;
[2116]45class ObjectPvs;
[1237]46
[1667]47
[2237]48#define COUNT_ORIGIN_OBJECTS 1
[2227]49#define USE_AVGRAYCONTRI 0
[1911]50
51
[2227]52
[1551]53/** View space / object space hierarchy statistics.
[1288]54*/
55class HierarchyStatistics: public StatisticsBase
56{
57public:
[1576]58        /// total number of entries in the pvs
[1624]59        int mPvsEntries;
[1640]60        /// storage cost in MB
61        float mMemory;
[1288]62        /// total number of nodes
[1624]63        int mNodes;
[1288]64        /// maximal reached depth
[1624]65        int mMaxDepth;
[1288]66        /// accumulated depth
[1624]67        int mAccumDepth;
[1449]68        /// time spent for queue repair
[1624]69        float mRepairTime;
70
[1449]71        // global cost ratio violations
72        int mGlobalCostMisses;
[1624]73        /// total cost of subdivision
74        float mTotalCost;
75        /// render cost decrease of subdivision
76        float mRenderCostDecrease;
[1313]77
[1288]78        // Constructor
79        HierarchyStatistics()
80        {
81                Reset();
82        }
83
[1624]84        int Nodes() const {return mNodes;}
[1640]85        int Interior() const { return mNodes / 2 - 1; }
[1624]86        int Leaves() const { return (mNodes / 2) + 1; }
[1288]87       
88        // TODO: computation wrong
[1624]89        double AvgDepth() const { return mAccumDepth / (double)Leaves();}
[1288]90
[1449]91        void Reset()
[1288]92        {
[1449]93                mGlobalCostMisses = 0;
[1624]94                mTotalCost = 0;
95                mRenderCostDecrease = 0;
96
97                mNodes = 0;
98                mMaxDepth = 0;
99                mAccumDepth = 0;
100                mRepairTime = 0;
101                mMemory = 0;
102                mPvsEntries = 0;
[1288]103        }
104
[2176]105        void Print(std::ostream &app) const;
[1288]106
[2176]107        friend std::ostream &operator<<(std::ostream &s, const HierarchyStatistics &stat)
[1288]108        {
109                stat.Print(s);
110                return s;
111        }
112};
113
114
[1723]115class HierarchySubdivisionStats
116{
117public:
118           
119        int mNumSplits;
120               
121        float mRenderCostDecrease;
122
123    float mTotalRenderCost;
124   
125        int mEntriesInPvs;
126   
127        float mMemoryCost;
128       
129        float mFullMemory;
130
131        int mViewSpaceSplits;
132
133        int mObjectSpaceSplits;
134
[1744]135        float mPriority;
[1723]136
137        float VspOspRatio() const { return (float)mViewSpaceSplits / (float)mObjectSpaceSplits; }
138
139        float FpsPerMb() const { return 1.0f / (mTotalRenderCost * mMemoryCost); }
140
141        HierarchySubdivisionStats() { Reset(); }
142
143        void Reset()
144        {
145                mNumSplits = 0;
146                mRenderCostDecrease = 0;
147                mTotalRenderCost = 0;
148                mEntriesInPvs = 0;
149                mMemoryCost = 0;
150                mFullMemory = 0;
151                mViewSpaceSplits = 0;
152                mObjectSpaceSplits = 0;
[1744]153                mPriority = 0;
[1723]154        }
155
156
[2176]157        void Print(std::ostream &app) const;
[1723]158
[2176]159        friend std::ostream &operator<<(std::ostream &s, const HierarchySubdivisionStats &stat)
[1723]160        {
161                stat.Print(s);
162                return s;
163        }
164};
165
166
[1237]167/** This class implements a structure holding two different hierarchies,
168        one for object space partitioning and one for view space partitioning.
169
170        The object space and the view space are subdivided using a cost heuristics.
171        If an object space split or a view space split is chosen is also evaluated
172        based on the heuristics.
173       
174        The view space heuristics is evaluated by weighting and adding the pvss of the back and
175        front node of each specific split. unlike for the standalone method vspbsp tree,
176        the pvs of an object would not be the pvs of single object but that of all objects
177        which are contained in the same leaf of the object subdivision. This could be done
178        by storing the pointer to the object space partition parent, which would allow access to all children.
179        Another possibility is to include traced kd-cells in the ray casing process.
180
181        Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object.
182        the contribution to an object to the pvs is the number of view cells it can be seen from.
183
184        @note
185        There is a potential efficiency problem involved in a sense that once a certain type
186        of split is chosen for view space / object space, the candidates for the next split of
187        object space / view space must be reevaluated.
188*/
189class HierarchyManager
190{
[2124]191        friend class VspOspViewCellsManager;
192
[1237]193public:
[2124]194       
[1421]195        /** Constructor with the view space partition tree and
196                the object space hierarchy type as argument.
[1237]197        */
[1421]198        HierarchyManager(const int objectSpaceHierarchyType);
[2124]199       
[1279]200        /** Hack: OspTree will copy the content from this kd tree.
201                Only view space hierarchy will be constructed.
202        */
[1421]203        HierarchyManager(KdTree *kdTree);
[1237]204
[1421]205        /** Deletes space partition and view space partition.
206        */
[1286]207        ~HierarchyManager();
208
[1237]209        /** Constructs the view space and object space subdivision from a given set of rays
210                and a set of objects.
211                @param sampleRays the set of sample rays the construction is based on
212                @param objects the set of objects
213        */
[1308]214        void Construct(
[1293]215                const VssRayContainer &sampleRays,
216                const ObjectContainer &objects,
217                AxisAlignedBox3 *forcedViewSpace);
[1237]218
[1259]219        enum
220        {
221                NO_OBJ_SUBDIV,
222                KD_BASED_OBJ_SUBDIV,
223                BV_BASED_OBJ_SUBDIV
224        };
[1237]225
[1370]226        enum
227        {
228                NO_VIEWSPACE_SUBDIV,
229                KD_BASED_VIEWSPACE_SUBDIV
230        };
231
[1259]232        /** The type of object space subdivison
233        */
[1370]234        int GetObjectSpaceSubdivisionType() const;     
[2003]235       
[1370]236        /** The type of view space space subdivison
237        */
238        int GetViewSpaceSubdivisionType() const;
[2003]239       
[1370]240        /** Sets a pointer to the view cells manager.
241        */             
[1279]242        void SetViewCellsManager(ViewCellsManager *vcm);
[2003]243       
[1370]244        /** Sets a pointer to the view cells tree.
245        */
[1279]246        void SetViewCellsTree(ViewCellsTree *vcTree);
[2003]247
[1370]248        /** Exports the object hierarchy to disc.
249        */
[1279]250        void ExportObjectSpaceHierarchy(OUT_STREAM &stream);
[1764]251       
[1421]252        /** Print out statistics.
253        */
[2176]254        void PrintHierarchyStatistics(std::ostream &stream) const;
[1279]255
[1421]256        /** Returns the view space partition tree.
257        */
[1379]258        VspTree *GetVspTree();
[1279]259
[1421]260        /** Returns object space bounding box.
261        */
[1416]262        AxisAlignedBox3 GetObjectSpaceBox() const;
[1379]263
[1421]264        /** Exports object space hierarchy for visualization.
265        */
[1626]266        void ExportObjectSpaceHierarchy(Exporter *exporter,
267                                                                        const ObjectContainer &objects,
[1764]268                                                                        AxisAlignedBox3 *bbox,
[1920]269                                                                        const float maxRenderCost,
[1626]270                                                                        const bool exportBounds = true) const;
[1279]271
[1421]272        /** Returns intersectable pierced by this ray.
273        */
[1626]274        Intersectable *GetIntersectable(const VssRay &ray, const bool isTermination) const;
[1743]275 
[1889]276        Intersectable *GetIntersectable(Intersectable *obj, const Vector3 &point) const;
277
[1626]278        /** Export object space partition bounding boxes.
279        */
280        void ExportBoundingBoxes(OUT_STREAM &stream, const ObjectContainer &objects);
281
[2176]282        friend std::ostream &operator<<(std::ostream &s, const HierarchyManager &hm)
[1419]283        {
[1421]284                hm.PrintHierarchyStatistics(s);
[1419]285                return s;
286        }
287
[1667]288        HierarchyStatistics &GetHierarchyStats() { return mHierarchyStats; };
289
290        inline bool ConsiderMemory() const { return mConsiderMemory; }
[1686]291       
[2332]292        void EvaluateSubdivision(std::ofstream &splitsStats,
[1745]293                                                          const int splitsStepSize,
[1919]294                                                          const bool useFilter,
295                                                          const bool useHisto,
296                                                          const int histoMem,
297                                                          const int pass);
[1709]298
299
[1718]300        void CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects);
301
[1845]302        int CompressObjectSpace();
[1843]303        void CreateUniqueObjectIds();
304
[1912]305        float EvalCorrectedPvs(const float pvsFront,
306                                                   const float totalPvs,
[2227]307                                                   const float raysPerObjects) const;
[1843]308
[1686]309
[2094]310        /** Casts line segment into the view cells tree.
311                @param origin the origin of the line segment
312                @param termination the end point of the line segment
313                @returns view cells intersecting the line segment.
314        */
315    int CastLineSegment(const Vector3 &origin,
316                                                const Vector3 &termination,
317                                                ViewCellContainer &viewcells,
318                                                const bool useMailboxing = true);
[2342]319
320#ifdef USE_SSE
321        int CastLineSegment(RayPacket &packet);
322#endif
323
324
[1237]325protected:
326
[2187]327        void PrintTimings(const bool osp);
328
[1625]329        /** Returns true if the global termination criteria were met.
330        */
[1237]331        bool GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const;
332
333        /** Prepare construction of the hierarchies, set parameters, compute
334                first split candidates.
335        */
[1779]336        void PrepareObjectSpaceSubdivision(SplitQueue &tQueue,
337                                                                           const VssRayContainer &sampleRays,
338                                                                           const ObjectContainer &objects);
[1237]339
[1625]340
[1640]341        /** Create bounding box and root.
342        */
343        void InitialiseObjectSpaceSubdivision(const ObjectContainer &objects);
344
345        /** Returns memory usage of object space hierarchy.
346        */
347        float GetObjectSpaceMemUsage() const;
348
[1667]349
[1625]350        //////////////////////////////
351        // the main loop
352
353        /** This is for interleaved construction / sequential construction.
354        */
355        void RunConstruction(const bool repairQueue,
356                                                 const VssRayContainer &sampleRays,
357                                                 const ObjectContainer &objects,
[1640]358                                                 AxisAlignedBox3 *forcedViewSpace);
[1449]359       
[1625]360        /** This is for interleaved construction using some objects
361                and some view space splits.
362        */
363        int RunConstruction(SplitQueue &splitQueue,
364                                                SubdivisionCandidateContainer &chosenCandidates,
[1667]365                                                //const float minRenderCostDecr,
366                                                SubdivisionCandidate *oldCandidate,
[1676]367                                                const int minSteps,
368                                                const int maxSteps);
[1625]369
370        /** Default subdivision method.
371        */
[1449]372        void RunConstruction(const bool repairQueue);
[2094]373       
374       
[1625]375        ////////////////////////////////////////////////
376
[1580]377        /** Evaluates the subdivision candidate and executes the split.
378        */
[1625]379        bool ApplySubdivisionCandidate(SubdivisionCandidate *sc,
380                                                                   SplitQueue &splitQueue,
[2224]381                                                                   //const bool repairQueue,
382                                                                   std::vector<SubdivisionCandidate *> &dirtyList
383                                                                   );
[1237]384
[1625]385        /** Tests if hierarchy construction is finished.
386        */
[1237]387        bool FinishedConstruction() const;
388
[1625]389        /** Returns next subdivision candidate from the split queue.
390        */
391        SubdivisionCandidate *NextSubdivisionCandidate(SplitQueue &splitQueue);
[1237]392
[1625]393        /** Repairs the dirty entries of the subdivision candidate queue. The
394                list of entries is given in the dirty list.
[1736]395
396                @returns number of repaired candidates
[1580]397        */
[1736]398        int RepairQueue(const SubdivisionCandidateContainer &dirtyList,
399                                        SplitQueue &splitQueue,
400                                        const bool recomputeSplitPlaneOnRepair);
[1237]401
[1625]402        /** Collect subdivision candidates which were affected by the splits from the
403                chosenCandidates list.
404        */
405        void CollectDirtyCandidates(const SubdivisionCandidateContainer &chosenCandidates,
406                                                                SubdivisionCandidateContainer &dirtyList);
407
[2332]408        /** Print subdivision stats for log.
[1580]409        */
[2332]410        void PrintSubdivisionStats();
[1237]411
[1625]412        void AddSubdivisionStats(const int splits,
413                                                         const float renderCostDecr,
414                                                         const float totalRenderCost,
415                                                         const int totalPvsEntries,
[1640]416                                                         const float memory,
[1654]417                                                         const float renderCostPerStorage,
418                                                         const float vspOspRatio);
[1237]419
[1625]420        /** Collect affected view space candidates.
421        */
422        void CollectViewSpaceDirtyList(SubdivisionCandidate *sc,
423                                                                   SubdivisionCandidateContainer &dirtyList);
[1259]424
[1625]425        /** Collect affected object space candidates.
426        */
427        void CollectObjectSpaceDirtyList(SubdivisionCandidate *sc,
428                                                                         SubdivisionCandidateContainer &dirtyList);
[1259]429               
[1625]430        /** Export object space partition tree.
431        */
432        void ExportOspTree(Exporter *exporter,
433                                           const ObjectContainer &objects) const;
[1259]434
[1625]435        /** Parse the environment variables.
436        */
[1418]437        void ParseEnvironment();
[1415]438
[1418]439        bool StartObjectSpaceSubdivision() const;
440        bool StartViewSpaceSubdivision() const;
441
[1667]442
[1625]443        ////////////////////////////
444        // Helper function for preparation of subdivision
[1286]445
[1625]446        /** Prepare bv hierarchy for subdivision
447        */
[1779]448        void PrepareBvHierarchy(SplitQueue &tQueue,
449                                                        const VssRayContainer &sampleRays,
450                                                        const ObjectContainer &objects);
[1286]451
[1625]452        /** Prepare object space kd tree for subdivision.
453        */
[1779]454        void PrepareOspTree(SplitQueue &tQueue,
455                                                const VssRayContainer &sampleRays,
456                                                const ObjectContainer &objects);
[1308]457
[1625]458        /** Prepare view space subdivision and add candidate to queue.
459        */
[1779]460        void PrepareViewSpaceSubdivision(SplitQueue &tQueue,
461                                                                         const VssRayContainer &sampleRays,
462                                                                         const ObjectContainer &objects);
[1625]463
464        /** Was object space subdivision already constructed?
465        */
[1313]466        bool ObjectSpaceSubdivisionConstructed() const;
[1625]467       
468        /** Was view space subdivision already constructed?
469        */
[1329]470        bool ViewSpaceSubdivisionConstructed() const;
[1311]471
[1625]472        /** Reset the split queue, i.e., reevaluate the split candidates.
473        */
[1640]474    void ResetQueue(SplitQueue &splitQueue, const bool recomputeSplitPlane);
[1313]475
[1625]476        /** After the suddivision has ended, do some final tasks.
477        */
[1654]478        void FinishObjectSpaceSubdivision(const ObjectContainer &objects,
479                                                                          const bool removeRayRefs = true) const;
[1313]480
[1625]481        /** Returns depth of object space subdivision.
482        */
[1370]483        int GetObjectSpaceSubdivisionDepth() const;
484
[1640]485        /** Returns number of leaves in object space subdivision.
486        */
487        int GetObjectSpaceSubdivisionLeaves() const;
[1663]488        int GetObjectSpaceSubdivisionNodes() const;
[1640]489
[1625]490        /** Construct object space partition interleaved with view space partition.
491                Each time the best object or view space candidate is selected
492                for the next split.
493        */
[1626]494        void ConstructInterleaved(const VssRayContainer &sampleRays,
495                                                          const ObjectContainer &objects,
496                                                          AxisAlignedBox3 *forcedViewSpace);
[1449]497
[1625]498        /** Construct object space partition interleaved with view space partition.
499                The method chooses a number candidates of each type for subdivision.
500                The number is determined by the "gradient", i.e., the render cost decrease.
501                Once this render cost decrease is lower than the render cost decrease
502                for the splits of previous type, the method will stop current subdivision and
503                evaluate if view space or object space would be the beneficial for the
504                next number of split.
505        */
[1626]506        void ConstructInterleavedWithGradient(const VssRayContainer &sampleRays,
507                                                                                  const ObjectContainer &objects,
508                                                                                  AxisAlignedBox3 *forcedViewSpace);
[1624]509
[1548]510        /** Use iteration to construct the object space hierarchy.
511        */
[1626]512        void ConstructMultiLevel(const VssRayContainer &sampleRays,
513                                                         const ObjectContainer &objects,
514                                                         AxisAlignedBox3 *forcedViewSpace);
[1449]515
[1640]516        /** Based on a given subdivision, we try to optimize using an
517                multiple iteration over view and object space.
518        */
519        void OptimizeMultiLevel(const VssRayContainer &sampleRays,                                                                                       
520                                                        const ObjectContainer &objects,
521                                                        AxisAlignedBox3 *forcedViewSpace);
522
[1548]523        /** Reset the object space subdivision.
524                E.g., deletes hierarchy and resets stats.
525                so construction can be restarted.
526        */
[1779]527        void ResetObjectSpaceSubdivision(SplitQueue &tQueue,
528                                                                         const VssRayContainer &rays,
529                                                                         const ObjectContainer &objects);
[1449]530
[1779]531        void ResetViewSpaceSubdivision(SplitQueue &tQueue,
532                                                                   const VssRayContainer &rays,
533                                                                   const ObjectContainer &objects,
534                                                                   AxisAlignedBox3 *forcedViewSpace);
[1557]535
[2073]536        void CreateTraversalTree();
[1614]537
[1686]538        ///////////////////////////
[1680]539
[2176]540        void ExportStats(std::ofstream &stats,
[1779]541                                         SplitQueue &tQueue,
542                                         const ObjectContainer &objects);
[1686]543
[1706]544        void CollectBestSet(const int maxSplits,
545                                                const float maxMemoryCost,
[1707]546                                                ViewCellContainer &viewCells,
[1706]547                                                vector<BvhNode *> &bvhNodes);
548
[1713]549        int ExtractStatistics(const int maxSplits,
550                                                  const float maxMemoryCost,
551                                                  float &renderCost,
552                                                  float &memory,
[1718]553                                                  int &pvsEntries,
554                                                  int &viewSpaceSplits,
[1745]555                                                  int &objectSpaceSplits,
[1919]556                                                  const bool useFilter,
557                                                  const bool useHisto,
558                                                  const int histoMem,
559                                                  const int pass,
560                                                  bool &histoUsed);
[1709]561
[2332]562        void ComputePvs(const ObjectPvs &pvs, float &triangles, int &pvsEntries);
[1787]563        void GetPvsIncrementially(ViewCell *vc, ObjectPvs &pvs) const;
[1786]564        void PullUpPvsIncrementally(ViewCell *viewCell) const;
565        void GetPvsRecursive(ViewCell *vc, ObjectPvs &pvs) const;
[1787]566        void GetPvsEfficiently(ViewCell *vc, ObjectPvs &pvs) const;
567
[1830]568        float EvalFullMem() const;
569
[2332]570        ViewCellsManager *GetViewCellsManager();
[1843]571
[1237]572protected:
573
[1627]574        /** construction types
575                sequential: construct first view space, then object space
576                interleaved: construct view space and object space fully interleaved
577                gradient: construct view space / object space until a threshold is reached
578                multilevel: iterate until subdivisions converge to the optimum.
579        */
580        enum {SEQUENTIAL, INTERLEAVED, GRADIENT, MULTILEVEL};
581
[1580]582        /// type of hierarchy construction
583        int mConstructionType;
584
585        /// Type of object space partition
[1308]586        int mObjectSpaceSubdivisionType;
[1580]587        /// Type of view space partition
[1329]588    int mViewSpaceSubdivisionType;
589
[1589]590        /// the traversal queue
591        SplitQueue mTQueue;
592       
[1580]593        ////////////
594        //-- helper variables
595       
596        // the original osp type
[1323]597        int mSavedObjectSpaceSubdivisionType;
[1580]598        // the original vsp type
[1329]599        int mSavedViewSpaceSubdivisionType;
[1911]600       
[1323]601
[1580]602        ///////////////////
603        // Hierarchies
604
605        /// view space hierarchy
[1259]606        VspTree *mVspTree;
[1580]607        /// object space partition kd tree
[1259]608        OspTree *mOspTree;
[1625]609
[1911]610        float mInitialRenderCost;
611       
[2227]612        //float mMaxAvgRayContri;
613        //float mMinAvgRayContri;
[1911]614
[2227]615        float mMaxAvgRaysPerObject;
616        float mMinAvgRaysPerObject;
[1911]617
[1895]618        // quick hack:
619public:
[1580]620        /// bounding volume hierarchy
[1259]621        BvHierarchy *mBvHierarchy;
[1580]622       
[2130]623        bool mUseTraversalTree;
624
[2228]625        float mMinRenderCost;
626
[1589]627protected:
[1237]628
629
[1580]630        //////////
[1576]631        //-- global termination criteria
632
[1580]633        /// the mininal acceptable cost ratio for a split
[1237]634        float mTermMinGlobalCostRatio;
[1580]635        /// the threshold for global cost miss tolerance
[1237]636        int mTermGlobalCostMissTolerance;
[1580]637        /// maximum number of leaves
638        int mTermMaxLeaves;
[1649]639        /// Maximal allowed memory consumption.
640        float mTermMaxMemory;
[1580]641
[1667]642
[1576]643        ////////////////////
644
[1667]645        /// number of minimal steps of the same type
[1640]646        int mMinStepsOfSameType;
[1684]647        int mMaxStepsOfSameType;
[1640]648
[1580]649        /// statistics about the hierarchy
[1288]650        HierarchyStatistics mHierarchyStats;
651
[1308]652        int mMinDepthForObjectSpaceSubdivion;
[1370]653        int mMinDepthForViewSpaceSubdivion;
[1580]654       
[1625]655        //int mMinRenderCostDecrease;
[1624]656
[2176]657        std::ofstream mSubdivisionStats;
[1314]658
[1580]659        /// if the queue should be repaired after a subdivision steps
[1314]660        bool mRepairQueue;
[1370]661
662        bool mStartWithObjectSpace;
[1580]663        /** if multi level construction method should be used
664                where we iterate over both hierarchies until we
665                converge to the optimum.
666        */
[1449]667        bool mUseMultiLevelConstruction;
[1640]668
[1580]669        /// number of iteration steps for multilevel approach   
670        int mNumMultiLevels;
[1640]671
[1633]672        /** if split plane should be recomputed for the repair.
673                Otherwise only the priority is recomputed, the
674                split plane itself stays the same
675        */
676        bool mRecomputeSplitPlaneOnRepair;
[1662]677
678        /** If memory should be considered during choosing
679                of the next split type during gradient method.
680        */
681        bool mConsiderMemory;
[1666]682
[2094]683        TraversalTree *mTraversalTree;
684
[1727]685        int mMaxRepairs;
686
[1679]687        int mTimeStamp;
[1667]688        friend VspTree;
689        friend OspTree;
690        friend BvHierarchy;
[1744]691
692        float mPriority;
693
[1667]694        friend ViewCellsParseHandlers;
695
[1750]696        ViewCellContainer mOldViewCells;
[1237]697};
698
699}
700
701#endif
Note: See TracBrowser for help on using the repository browser.