source: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp @ 225

Revision 225, 10.2 KB checked in by mattausch, 19 years ago (diff)

updated bsp trees

Line 
1#include "Plane3.h"
2#include "ViewCellBsp.h"
3#include "Mesh.h"
4
5#include "ViewCell.h"
6#include <stack>
7
8#define DEL_PTR(ptr) while (0) {if (ptr) {delete (ptr); (ptr) = NULL;}}
9
10//namespace GtpVisibilityPreprocessor {
11/****************************************************************/
12/*                  class BspNode implementation                */
13/****************************************************************/
14bool BspNode::IsRoot() const
15{
16        return mParent == NULL;
17}
18
19BspInterior *BspNode::GetParent()
20{
21        return mParent;
22}
23/****************************************************************/
24/*              class BspInterior implementation                */
25/****************************************************************/
26
27
28BspInterior::BspInterior(Plane3 plane): mPlane(plane)
29{}
30
31bool BspInterior::IsLeaf() const
32{
33        return false;
34}
35
36BspNode *BspInterior::GetBack()
37{
38        return mBack;
39}
40
41BspNode *BspInterior::GetFront()
42{
43        return mFront;
44}
45
46Plane3 *BspInterior::GetPlane()
47{
48        return &mPlane;
49}
50
51void BspInterior::ReplaceChildLink(BspNode *oldChild, BspNode *newChild)
52{
53        if (mBack == oldChild)
54        {
55                mBack = newChild;
56        }
57    else
58        {
59                mFront = newChild;
60        }
61}
62
63void BspInterior::SetupChildLinks(BspNode *b, BspNode *f)
64{
65    mBack = b;
66    mFront = f;
67}
68
69/****************************************************************/
70/*                  class BspLeaf implementation                */
71/****************************************************************/
72
73BspLeaf::BspLeaf(ViewCell *viewCell): mViewCell(viewCell)
74{
75}
76
77ViewCell *BspLeaf::GetViewCell()
78{
79        return mViewCell;
80}
81
82bool BspLeaf::IsLeaf() const
83{
84        return true;
85}
86
87/****************************************************************/
88/*                  class Polygon implementation                */
89/****************************************************************/
90
91Polygon::Polygon()
92{}
93
94Polygon::Polygon(const VertexContainer &vertices): mVertices(vertices)
95{}
96
97Polygon::Polygon(Face *face, Mesh *parent)
98{
99        VertexIndexContainer::const_iterator it;
100
101        for (it = face->mVertexIndices.begin(); it != face->mVertexIndices.end(); ++ it)
102        {
103                mVertices.push_back(parent->mVertices[*it]);
104        }
105}
106
107Plane3 Polygon::GetSupportingPlane()
108{
109        return Plane3(mVertices[0], mVertices[1], mVertices[2]);
110}
111
112void Polygon::DeletePolygons(PolygonQueue *polys)
113{
114        // don't need to store polygon information = delete polygons
115        while(!polys->empty())
116        {
117                Polygon *poly = polys->front();
118                polys->pop();
119                DEL_PTR(poly);
120        }
121
122}
123
124void Polygon::Split(Plane3 *partition, Polygon *front, Polygon *back)
125{
126        Vector3 ptA = mVertices[mVertices.size() - 1];;
127       
128        int sideA = partition->Side(ptA);
129       
130        VertexContainer::const_iterator it;
131
132        // find line - plane intersections
133        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
134        {
135                Vector3 ptB = (*it);
136                int sideB = partition->Side(ptB);
137
138                // vertices on different sides => split
139                if ((sideA != 0) && (sideB != 0) && (sideA != sideB))
140                {
141                        Vector3 v = ptB - ptA; // line from A to B
142                        float dv = DotProd(partition->mNormal, v);
143                        float t = 0;
144                       
145                        if (dv)
146                        {
147                                t = - partition->Distance(ptA) / dv;
148                        }
149                }
150                if (sideB >= 0)
151                {
152                        back->mVertices.push_back(ptB);
153                }
154                else if (sideB <= 0)
155                {
156                        front->mVertices.push_back(ptB);
157                }
158
159                ptA = ptB;
160                sideA = sideB;
161        }
162}
163
164int Polygon::Side(Plane3 *plane)
165{
166        VertexContainer::const_iterator it;
167
168        bool onFrontSide = false;
169        bool onBackSide = false;
170
171        // find line - plane intersections
172        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
173        {
174                int side = plane->Side(*it);
175               
176                if (side > 0)
177                {
178                        onFrontSide = true;
179                }
180                else if (side < 0)
181                {
182                        onBackSide = true;
183                }
184
185                if (onFrontSide && onBackSide) // splits
186                        return SPLIT;
187        }
188
189        if (onBackSide)
190        {
191                return BACK_SIDE;
192        }
193        else if (onFrontSide)
194        {
195                return FRONT_SIDE;
196        }
197
198        return COINCIDENT;
199}
200
201/****************************************************************/
202/*                  class BspTree implementation                */
203/****************************************************************/
204
205BspTree::BspTree(const ViewCellContainer &viewCells):
206mMaxPolys(0), mMaxDepth(0), mRoot(NULL)
207{
208        //mRootCell = cell;
209        Subdivide(viewCells);
210}
211
212BspTree::BspTree(const ObjectContainer &objects, int maxPolys, int maxDepth):
213mMaxPolys(maxPolys), mMaxDepth(maxDepth)
214{
215        mRoot = new BspLeaf();
216
217        Subdivide(objects);
218}
219 
220BspTree::~BspTree()
221{
222        std::stack<BspNode *> tStack;
223
224        tStack.push(mRoot);
225
226        while (!tStack.empty())
227        {
228                BspNode *node = tStack.top();
229
230            tStack.pop();
231       
232                if (!node->IsLeaf())
233                {
234                        BspInterior *interior = dynamic_cast<BspInterior *>(node);
235
236                        // push the children on the stack (there are always two children)
237                        interior->GetBack()->mParent = NULL;
238                        interior->GetFront()->mParent = NULL;
239
240                        tStack.push(interior->GetBack());
241                        tStack.push(interior->GetFront());
242                }
243
244                DEL_PTR(node);
245        }
246}
247
248
249void BspTree::InsertViewCell(ViewCell *viewCell)
250{
251        std::stack<BspTraversalData> tStack;
252       
253        PolygonQueue polys;
254        // copy polygon information to guide the split process
255        CopyMesh2Polygon(viewCell->GetMesh(), polys);
256
257        tStack.push(BspTraversalData(mRoot, NULL, &polys, 0));
258
259        while (!tStack.empty())
260        {
261                /*BspNode *node = tStack.top();
262
263            tStack.pop();
264       
265                if (!node->IsLeaf())
266                {
267                        BspInterior *interior = dynamic_cast<BspInterior *>(node);
268
269                        // push the children on the stack (there are always two children)
270                        interior->GetBack()->mParent = NULL;
271                        interior->GetFront()->mParent = NULL;
272
273                        tStack.push(interior->GetBack());
274                        tStack.push(interior->GetFront());
275                }
276
277                DEL_PTR(node);*/
278        }
279/*      BspNode *currentNode = mRoot;
280 
281        std::stack<BspTraversalData> tStack;
282        //  stack<STraversalData> tStack;
283
284        //tStack.push(tdata);
285
286        while (!tStack.empty())
287        {
288            BspTraversalData data = tStack.top();
289
290            tStack.pop();
291   
292                Mesh backPolys;
293                Mesh frontPolys;
294
295                if (data.mNode->IsLeaf()) // if we have a leaf => subdivide
296                {
297                        BspNode *node = SubdivideNode(dynamic_cast<BspLeaf *>(data.mNode),
298                                                                                  data.mParent,
299                                                                                  data.mPolys,
300                                                                              data.mDepth,
301                                                                                  backPolys,
302                                                                                  frontPolys);
303       
304                        if (!node->IsLeaf()) // node was subdivided
305                        {
306                                BspInterior *interior = dynamic_cast<BspInterior *>(node);
307
308                                // push the children on the stack (there are always two children)
309                                //tStack.push(BspTraversalData(interior->GetBack(), interior, backPolys, data.mDepth + 1));
310                                //tStack.push(BspTraversalData(interior->GetFront(), interior, frontPolys, data.mDepth + 1));
311                        }
312                }
313        }*/
314}
315
316void BspTree::Subdivide(const ViewCellContainer &viewCells)
317{
318}
319
320void BspTree::CopyMesh2Polygon(Mesh *mesh, PolygonQueue &polys)
321{
322        FaceContainer::const_iterator fi;
323        // copy the face data to polygons
324        for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)
325        {
326                Polygon *poly = new Polygon((*fi), mesh);
327                polys.push(poly);
328        }
329}
330
331void BspTree::Copy2PolygonSoup(const ObjectContainer &objects, PolygonQueue &polys)
332{
333        ObjectContainer::const_iterator it, it_end = objects.end();
334
335        for (it = objects.begin(); it != it_end; ++ it)
336        {
337                Intersectable *object = *it;
338
339                // extract the mesh instances
340                if (object->Type() == Intersectable::MESH_INSTANCE)
341                {
342                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
343
344                        Mesh *mesh = inst->GetMesh();
345
346                        // copy the mesh data to polygons
347                        CopyMesh2Polygon(mesh, polys);
348                }
349        }
350}
351
352void BspTree::Subdivide(const ObjectContainer &objects)
353{
354        std::stack<BspTraversalData> tStack;
355        PolygonQueue polys;
356       
357        // copy mesh instance polygons into one big polygon soup
358        Copy2PolygonSoup(objects, polys);
359
360        BspTraversalData tdata(mRoot, mRoot->GetParent(), &polys, 0);
361        tStack.push(tdata);
362
363        while (!tStack.empty())
364        {
365            BspTraversalData data = tStack.top();
366
367            tStack.pop();
368   
369                PolygonQueue *backPolys = new PolygonQueue();
370                PolygonQueue *frontPolys = new PolygonQueue();
371
372                BspNode *node = SubdivideNode(dynamic_cast<BspLeaf *>(data.mNode),
373                                                                          data.mParent,
374                                                                          data.mPolys,
375                                                                      data.mDepth,
376                                                                          backPolys,
377                                                                          frontPolys);
378       
379                if (!node->IsLeaf()) // node was subdivided
380                {
381                        BspInterior *interior = dynamic_cast<BspInterior *>(node);
382
383                        // push the children on the stack (there are always two children)
384                        tStack.push(BspTraversalData(interior->GetBack(), interior, backPolys, data.mDepth + 1));
385                        tStack.push(BspTraversalData(interior->GetFront(), interior, frontPolys, data.mDepth + 1));
386                }
387        }
388}
389
390Plane3 BspTree::SelectPlane(PolygonQueue *polyQueue)
391{
392        // TODO: more sophisticated criteria
393        return polyQueue->front()->GetSupportingPlane();
394}
395
396BspNode *BspTree::SubdivideNode(BspLeaf *leaf, BspInterior *parent,
397                                                                PolygonQueue *polys, const int depth,
398                                                                PolygonQueue *frontPolys, PolygonQueue *backPolys)
399{
400        // terminate traversal if no more faces in mesh
401        if ((polys->size() <= mMaxPolys) || (depth >= mMaxDepth))
402        {
403                // don't need to store polygon information = delete polygons
404                Polygon::DeletePolygons(polys);
405               
406                return leaf;
407        }
408
409        // add the new nodes to the tree + select subdivision plane
410        BspInterior *node = new BspInterior(SelectPlane(polys));
411
412        while (!polys->empty())
413        {
414                Polygon *poly = polys->front();
415
416                polys->pop();
417
418                int  result = 0;// = node->GetPlane()->Side(node->GetPlane());
419
420                Polygon *front_piece = NULL;
421                Polygon *back_piece = NULL;
422
423                switch (result)
424                {
425                        case Polygon::COINCIDENT:
426                        case Polygon::FRONT_SIDE:
427                                frontPolys->push(poly);
428                                break;
429                        case Polygon::BACK_SIDE:
430                                backPolys->push(poly);
431                                break;
432                        case Polygon::SPLIT:
433                                front_piece = new Polygon();
434                                back_piece = new Polygon();
435
436                                //-- split polygon
437                poly->Split(node->GetPlane(), front_piece, back_piece);
438
439
440                                backPolys->push(back_piece);
441                                frontPolys->push(front_piece);
442
443                                // don't need polygon anymore
444                                DEL_PTR(poly);
445                                break;
446                        default:
447                                frontPolys->push(poly);
448                                break;
449                }
450        }
451
452        // backside of convex view cell polygon => outside
453        BspLeaf *back = new BspLeaf();
454        BspLeaf *front = new BspLeaf();
455
456        // replace a link from node's parent
457        if (parent)
458        {
459                parent->ReplaceChildLink(leaf, node);
460        }
461
462        // and setup child links
463        node->SetupChildLinks(back, front);
464
465        DEL_PTR(leaf);
466
467        return node;
468}
469
470//} // GtpVisibilityPreprocessor
Note: See TracBrowser for help on using the repository browser.