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

Revision 2848, 4.4 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 CompDist(RenderQueueBucket *b1, RenderQueueBucket *b2)
18{
19        return (b1->mMinDistance < b2->mMinDistance);
20}
21
22
23
24RenderQueue::RenderQueue():
25mState(NULL),
26mMinSizeForSorting(3),
27mCamera(NULL),
28mNumEntries(0)
29{
30}
31
32
33RenderQueue::RenderQueue(RenderState *state, Camera *cam):
34mState(state),
35mMinSizeForSorting(3),
36mCamera(cam),
37mNumEntries(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        if (mat->IsCullFaceEnabled() != mBuckets[idx]->mCullFaceEnabled)
61                return false;
62
63        const bool hasTexture = (mat->GetTexture() != NULL);
64
65        if (hasTexture != mBuckets[idx]->mHasTexture)
66                return false;
67
68        if (hasTexture)
69        {
70                if (mat->GetTexture()->GetWidth() != mBuckets[idx]->mTexWidth)
71                        return false;
72
73                if (mat->GetTexture()->GetHeight() != mBuckets[idx]->mTexHeight)
74                        return false;
75        }
76
77        return true;
78}
79
80
81void RenderQueue::Enqueue(SceneEntity *entity)
82{
83        ShapeContainer::iterator sit, sit_end;
84
85        entity->GetCurrentLODLevel(sit, sit_end);
86
87        for (; sit != sit_end; ++ sit)
88        {
89                Enqueue(*sit);
90        }
91}
92
93
94void RenderQueue::Enqueue(Shape *shape)
95{
96        RenderQueueBucket *bucket;
97        ++ mNumEntries;
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                        bucket->mMinDistance = -1;
120
121                        Material *mat = shape->GetMaterial();
122
123                        bucket->mAlphaTestEnabled = mat->IsAlphaTestEnabled();
124                        bucket->mCullFaceEnabled = mat->IsCullFaceEnabled();
125
126                        const bool hasTexture = (mat->GetTexture() != NULL);
127
128                        bucket->mHasTexture = hasTexture;
129
130                        bucket->mTexWidth = hasTexture ? mat->GetTexture()->GetWidth() : 0;
131                        bucket->mTexHeight = hasTexture ? mat->GetTexture()->GetHeight() : 0;
132
133                        mBuckets.push_back(bucket);
134
135                        //cout << "num buckets: " << (int)mBuckets.size() << endl;
136                }
137
138                bucket = mBuckets[i];
139                shape->mRenderQueueBucket = bucket;
140        }
141
142        if (bucket->mMinDistance < .0f)
143        {
144                // assume that the incoming nodes are ordered by distance
145                // => set min dist on first incoming node
146                const Vector3 v = shape->GetCenter() - mCamera->GetPosition();
147               
148                const float dist = SqrMagnitude(v);
149                bucket->mMinDistance = dist;
150        }
151
152        bucket->mShapes.push_back(shape);
153}
154
155
156void RenderQueue::Clear()
157{
158        for (size_t i = 0; i < mBuckets.size(); ++ i)
159        {
160                mBuckets[i]->mMinDistance = -1;
161                mBuckets[i]->mShapes.clear();
162        }
163
164        mNumEntries = 0;
165}
166
167
168void RenderQueue::SetRenderState(RenderState *state)
169{
170        mState = state;
171}
172
173
174void RenderQueue::Render()
175{
176        // sort the buckets
177        Sort();
178
179        // render all buckets
180        for (size_t i = 0; i < mBuckets.size(); ++ i)
181        {
182                ShapeContainer::const_iterator sit, sit_end = mBuckets[i]->mShapes.end();
183
184                for (sit = mBuckets[i]->mShapes.begin(); sit != sit_end; ++ sit)
185                {
186                        Shape *shape = *sit;
187                        shape->Render(mState);
188                }
189        }
190        //Print();
191}
192
193
194void RenderQueue::Print()
195{
196        for (size_t i = 0; i < mBuckets.size(); ++ i)
197        {
198                Debug << "\n******\nbucket " << (int)i << endl;
199
200                ShapeContainer::const_iterator sit, sit_end = mBuckets[i]->mShapes.end();
201
202                for (sit = mBuckets[i]->mShapes.begin(); sit != sit_end; ++ sit)
203                {
204                        Shape *shape = *sit;
205                       
206                        Material *mat = shape->GetMaterial();
207                        int tsize = mat->GetTexture() ? mat->GetTexture()->GetByteSize() : 0;
208                       
209                        float dist = SqrMagnitude(shape->GetBoundingBox().Center() - mCamera->GetPosition());
210                       
211                        Debug << "e: " << shape << " a: " << mat->IsAlphaTestEnabled() << " s: " << tsize << " d: " << dist << " " << endl;
212                }
213        }
214}
215
216
217void RenderQueue::Sort()
218{
219        // sort buckets itself
220        sort(mBuckets.begin(), mBuckets.end(), CompDist);
221}
222
223
224void RenderQueue::Apply()
225{
226        Render();
227        Clear();
228}
229
230
231}
Note: See TracBrowser for help on using the repository browser.