source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderQueue.cpp @ 2842

Revision 2842, 4.3 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include "RenderQueue.h"
2#include "SceneEntity.h"
3#include "Geometry.h"
4#include "Texture.h"
5#include "Material.h"
6#include "Camera.h"
7#include "Shape.h"
8
9
10using namespace std;
11
12
13namespace CHCDemoEngine
14{
15
16
17inline static bool CompDist2(RenderQueueBucket *b1, RenderQueueBucket *b2)
18{
19        return (b1->mMinDistance < b2->mMinDistance);
20}
21
22
23
24RenderQueue::RenderQueue():
25mState(NULL),
26mMinSizeForSorting(3),
27mCamera(NULL),
28mSize(0)
29{
30}
31
32
33RenderQueue::RenderQueue(RenderState *state, Camera *cam):
34mState(state),
35mMinSizeForSorting(3),
36mCamera(cam),
37mSize(0)
38{
39}
40
41
42RenderQueue::~RenderQueue()
43{
44        for (size_t i = 0; i < mBuckets.size(); ++ i)
45        {
46                DEL_PTR(mBuckets[i]);
47        }
48}
49
50
51bool RenderQueue::FitsInBucket(Shape *shape, size_t idx) const
52{
53        Material *mat = shape->GetMaterial();
54
55        // test if entity belongs to this bucket
56        // note: rather slows down the application for some reason!!
57        if (mat->IsAlphaTestEnabled() != mBuckets[idx]->mAlphaTestEnabled)
58                return false;
59
60        const bool hasTexture = (mat->GetTexture() != NULL);
61
62        if (hasTexture != mBuckets[idx]->mHasTexture)
63                return false;
64
65        if (hasTexture)
66        {
67                if (mat->GetTexture()->GetWidth() != mBuckets[idx]->mTexWidth)
68                        return false;
69
70                if (mat->GetTexture()->GetHeight() != mBuckets[idx]->mTexHeight)
71                        return false;
72        }
73
74        return true;
75}
76
77
78void RenderQueue::Enqueue(SceneEntity *entity)
79{
80        static ShapeContainer shapes;
81        shapes.clear();
82
83        entity->GetCurrentLODLevel(shapes);
84
85        ShapeContainer::const_iterator sit, sit_end = shapes.end();
86
87        for (sit = shapes.begin(); sit != sit_end; ++ sit)
88        {
89                Enqueue(*sit);
90        }
91}
92
93
94void RenderQueue::Enqueue(Shape *shape)
95{
96        RenderQueueBucket *bucket;
97        ++ mSize;
98       
99        if (shape->mRenderQueueBucket)
100        {
101                bucket = shape->mRenderQueueBucket;
102        }
103        else
104        {
105                bool bucketFound = false;
106
107                size_t i = 0;
108
109                for (; i < mBuckets.size(); ++ i)
110                {
111                        if (bucketFound = FitsInBucket(shape, i))
112                                break;
113                }
114
115                // create new bucket
116                if (!bucketFound)
117                {
118                        RenderQueueBucket *bucket = new RenderQueueBucket();
119
120                        Material *mat = shape->GetMaterial();
121
122                        bucket->mAlphaTestEnabled = mat->IsAlphaTestEnabled();
123
124                        const bool hasTexture = (mat->GetTexture() != NULL);
125
126                        bucket->mHasTexture = hasTexture;
127
128                        bucket->mTexWidth = hasTexture ? mat->GetTexture()->GetWidth() : 0;
129                        bucket->mTexHeight = hasTexture ? mat->GetTexture()->GetHeight() : 0;
130
131                        mBuckets.push_back(bucket);
132
133                        // assume that the incoming nodes are ordered by distance => set min dist
134                        // on first incoming node
135                        Vector3 v = shape->GetTransformedBoundingBox().Center() - mCamera->GetPosition();
136                        const float dist = SqrMagnitude(v);
137                        mBuckets[i]->mMinDistance = dist;
138
139                        //cout << "num buckets: " << (int)mBuckets.size() << endl;
140                }
141
142                bucket = mBuckets[i];
143                shape->mRenderQueueBucket = bucket;
144        }
145
146        bucket->mShapes.push_back(shape);
147}
148
149
150void RenderQueue::Clear()
151{
152        for (size_t i = 0; i < mBuckets.size(); ++ i)
153                mBuckets[i]->mShapes.clear();
154
155        mSize = 0;
156}
157
158
159void RenderQueue::SetRenderState(RenderState *state)
160{
161        mState = state;
162}
163
164
165void RenderQueue::Render()
166{
167        // sort the buckets
168        Sort();
169
170        // render all buckets
171        for (size_t i = 0; i < mBuckets.size(); ++ i)
172        {
173                ShapeContainer::const_iterator sit, sit_end = mBuckets[i]->mShapes.end();
174
175                for (sit = mBuckets[i]->mShapes.begin(); sit != sit_end; ++ sit)
176                {
177                        Shape *shape = *sit;
178                        shape->Render(mState);
179                }
180        }
181
182        //Print();
183}
184
185
186void RenderQueue::Print()
187{
188        for (size_t i = 0; i < mBuckets.size(); ++ i)
189        {
190                Debug << "\n******\nbucket " << (int)i << endl;
191
192                ShapeContainer::const_iterator sit, sit_end = mBuckets[i]->mShapes.end();
193
194                for (sit = mBuckets[i]->mShapes.begin(); sit != sit_end; ++ sit)
195                {
196                        Shape *shape = *sit;
197                       
198                        Material *mat = shape->GetMaterial();
199                        int tsize = mat->GetTexture() ? mat->GetTexture()->GetByteSize() : 0;
200                       
201                        float dist = SqrMagnitude(shape->GetBoundingBox().Center() - mCamera->GetPosition());
202                       
203                        Debug << "e: " << shape << " a: " << mat->IsAlphaTestEnabled() << " s: " << tsize << " d: " << dist << " " << endl;
204                }
205        }
206}
207
208
209void RenderQueue::Sort()
210{
211        // sort buckets itself
212        sort(mBuckets.begin(), mBuckets.end(), CompDist2);
213}
214
215
216void RenderQueue::Apply()
217{
218        Render();
219        Clear();
220}
221
222
223}
Note: See TracBrowser for help on using the repository browser.