00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include<queue>
00013 #include <stack>
00014
00015 #define GLEW_STATIC
00016 #include <GL/glew.h>
00017
00018 #include "ChcRenderer.h"
00019 #include "../../core/src/geometrynode.h"
00020
00021 using namespace VRUT;
00022
00023 bool
00024 ChcRenderer::Initialize() {
00025
00026 if (!initialized) {
00027 bool res = RenderGlModule::Initialize();
00028
00029 GLenum err = glewInit();
00030
00031
00032
00033
00034
00035 if (res) {
00036 vector<OcclusionQuery *> queries;
00037 const int nq = 1000;
00038 OcclusionQuery::GenQueries(queries, nq);
00039 for (int i=0; i < nq; i++)
00040 occlusionQueries.push(queries[i]);
00041 }
00042 initialized = res;
00043 }
00044
00045 return initialized;
00046 }
00047
00048
00049 void
00050 ChcRenderer::DrawNode(const GeometryNode *node)
00051 {
00052 if (!node->IsActive())
00053 return;
00054
00055 glPushMatrix();
00056 glMultMatrixf(node->GetWorldTransMatrix()->_m);
00057
00059 if (useVBO && vboSupported)
00060 drawVBO(node);
00061 else
00062 drawDispList(node);
00063
00064 glPopMatrix();
00065 }
00066
00067 void
00068 ChcRenderer::DrawItems(BVH::ItemsList &itemsList)
00069 {
00070
00071 for (BVH::ItemsList::const_iterator nodeIt = itemsList.begin();
00072 nodeIt != itemsList.end();
00073 nodeIt++)
00074 {
00075 const GeometryNode * node = (const GeometryNode *)scene->GetNode(*nodeIt);
00076 if (!node->IsActive())
00077 continue;
00078
00079 glPushMatrix();
00080 glMultMatrixf(node->GetWorldTransMatrix()->_m);
00081
00083 if (useVBO && vboSupported)
00084 drawVBO(node);
00085 else
00086 drawDispList(node);
00087
00088 glPopMatrix();
00089 }
00090 }
00091
00092 void
00093 ChcRenderer::DrawItemsReverse(BVH::BlendedList &itemsList)
00094 {
00095
00096 for (BVH::BlendedList::const_reverse_iterator nodeIt = itemsList.rbegin();
00097 nodeIt != itemsList.rend();
00098 nodeIt++)
00099 {
00100 const GeometryNode * node = (const GeometryNode *)scene->GetNode(nodeIt->second);
00101 if (!node->IsActive())
00102 continue;
00103
00104 glPushMatrix();
00105 glMultMatrixf(node->GetWorldTransMatrix()->_m);
00106
00108 if (useVBO && vboSupported)
00109 drawVBO(node);
00110 else
00111 drawDispList(node);
00112
00113 glPopMatrix();
00114 }
00115 }
00116
00117
00118
00119 void
00120 ChcRenderer::RenderBox(const AABB &box)
00121 {
00122
00123 glBegin(GL_QUADS);
00124 glVertex3d(box.MinBound.x, box.MaxBound.y, box.MinBound.z );
00125 glVertex3d(box.MaxBound.x, box.MaxBound.y, box.MinBound.z );
00126 glVertex3d(box.MaxBound.x, box.MinBound.y, box.MinBound.z );
00127 glVertex3d(box.MinBound.x, box.MinBound.y, box.MinBound.z );
00128
00129 glVertex3d(box.MinBound.x, box.MinBound.y, box.MaxBound.z );
00130 glVertex3d(box.MaxBound.x, box.MinBound.y, box.MaxBound.z );
00131 glVertex3d(box.MaxBound.x, box.MaxBound.y, box.MaxBound.z );
00132 glVertex3d(box.MinBound.x, box.MaxBound.y, box.MaxBound.z );
00133
00134 glVertex3d(box.MaxBound.x, box.MinBound.y, box.MinBound.z );
00135 glVertex3d(box.MaxBound.x, box.MinBound.y, box.MaxBound.z );
00136 glVertex3d(box.MaxBound.x, box.MaxBound.y, box.MaxBound.z );
00137 glVertex3d(box.MaxBound.x, box.MaxBound.y, box.MinBound.z );
00138
00139 glVertex3d(box.MinBound.x, box.MinBound.y, box.MinBound.z );
00140 glVertex3d(box.MinBound.x, box.MinBound.y, box.MaxBound.z );
00141 glVertex3d(box.MinBound.x, box.MaxBound.y, box.MaxBound.z );
00142 glVertex3d(box.MinBound.x, box.MaxBound.y, box.MinBound.z );
00143
00144 glVertex3d(box.MinBound.x, box.MinBound.y, box.MinBound.z );
00145 glVertex3d(box.MaxBound.x, box.MinBound.y, box.MinBound.z );
00146 glVertex3d(box.MaxBound.x, box.MinBound.y, box.MaxBound.z );
00147 glVertex3d(box.MinBound.x, box.MinBound.y, box.MaxBound.z );
00148
00149 glVertex3d(box.MinBound.x, box.MaxBound.y, box.MinBound.z );
00150 glVertex3d(box.MaxBound.x, box.MaxBound.y, box.MinBound.z );
00151 glVertex3d(box.MaxBound.x, box.MaxBound.y, box.MaxBound.z );
00152 glVertex3d(box.MinBound.x, box.MaxBound.y, box.MaxBound.z );
00153
00154 glEnd();
00155 }
00156
00157
00158 void
00159 ChcRenderer::Draw()
00160 {
00161 frame++;
00162
00164 glClearColor(0.4, 0.3, 0.6, 0.0);
00165 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00166
00167 wxMutexLocker paramsLocker(paramsMutex);
00168 scene = GetSceneMgr()->GetScene(GetSceneID());
00169 if (!scene)
00170 return;
00171
00172
00173 Camera *pcam = (Camera *)scene->GetNode(cameraID);
00174
00175
00176 BVH * bvh = scene->GetBVH();
00177 if (!pcam || !bvh || !Initialize())
00178 {
00179 scene = (Scene *)NULL;
00180 return;
00181 }
00182
00184 bool wrLockNeeded = !pcam->IsValid();
00185
00186 if (wrLockNeeded)
00187 pcam->WriteLock();
00188 else
00189 pcam->ReadLock();
00190
00191
00192 Camera camera = *pcam;
00193
00194 if (wrLockNeeded)
00195 pcam->WriteUnlock();
00196 else
00197 pcam->ReadUnlock();
00198
00199 vboRenderUpdated = false;
00201 ResetNodes();
00202
00204 glMatrixMode(GL_PROJECTION);
00205
00207
00208
00209
00210
00211
00212
00213 scene->UpdateTransformation(camera.GetID());
00214 unsigned w, h;
00215 camera.GetWidthHeight(&w, &h);
00216 glViewport(0, 0, w, h);
00217 glLoadMatrixf(camera.GetProjectionMatrix()->_m);
00219 glMatrixMode(GL_MODELVIEW);
00220 glLoadMatrixf(camera.GetWorldTransMatrix()->Inverse()._m);
00221
00222
00223
00224 if (drawBVH) {
00225 LOG(wxString::Format(wxT("DraBVH: %i"), drawBVH));
00226 drawBVHHierarchy();
00227 }
00228
00229
00230 drawLights();
00231
00232
00233 if (nodeInfo.size() != bvh->numberOfNodes) {
00234 LOG(wxString::Format(wxT("Number of nodes: %i"), bvh->numberOfNodes));
00235 nodeInfo.resize(bvh->numberOfNodes);
00236 for (unsigned int i=0; i < nodeInfo.size(); i++)
00237 nodeInfo[i].lastVisibleFrame = 24390252;
00238 }
00239
00240
00241 vector<const GeometryNode *> blendedNodes;
00242 priority_queue< NodeInfo > nodeStack;
00243
00244
00245
00246 queue<QueryInfo> queryQueue;
00247
00248 nodeStack.push(NodeInfo(0, (BVHNode *)bvh->GetRoot(), 0.0f));
00249 VECTOR3 cameraPos = camera.GetWorldTransMatrix()->ExtractTranslation();
00250
00251 renderedNodes = 0;
00252 renderedBlendedNodes = 0;
00253 queriedNodes = 0;
00254 while (!nodeStack.empty() || !queryQueue.empty()) {
00255
00256
00257 while (!queryQueue.empty() &&
00258 queryQueue.front().query->ResultAvailable()) {
00259 QueryInfo *qi = &queryQueue.front();
00260
00261 if (qi->query->GetQueryResult() != 0) {
00262 if (!qi->info.node->IsLeaf() ||
00263 nodeInfo[qi->info.node->id].lastVisibleFrame != frame-1)
00264 ProcessNode(qi->info,
00265 cameraPos,
00266 qi->info.planeMask,
00267 blendedNodes,
00268 nodeStack);
00269 PullUpVisibility(qi->info.node);
00270 } else {
00271
00272
00273
00274 }
00275
00276 queryQueue.pop();
00277 occlusionQueries.push(qi->query);
00278 }
00279
00280 if (!nodeStack.empty()) {
00281
00282 NodeInfo info = nodeStack.top();
00283 nodeStack.pop();
00284
00285
00286 bvh->UpdateBV(info.node);
00287 Camera::VFC_RESULT result = Camera::INTERSECT;
00288 unsigned int planeMask = info.planeMask;
00290
00291 if (!info.node->GetAABB()->PointIsIn(cameraPos)) {
00292 if (planeMask!=63) {
00293
00295 if (!info.node->GetBSphere()->Intersects(camera.GetBSphere()))
00296 result = Camera::OUTSIDE;
00297 else
00299 result = camera.InFrustum(*info.node->GetAABB(),
00300 &info.node->LastOut(),
00301 &planeMask);
00302 }
00303
00304 if (result != Camera::OUTSIDE) {
00305 if (info.node->IsLeaf() ||
00306 (nodeInfo[info.node->id].lastVisibleFrame != frame-1)
00307 ) {
00308 queriedNodes++;
00309
00310 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT);
00311
00312 glDisable(GL_CULL_FACE);
00313 glDepthMask(GL_FALSE);
00314 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
00315
00316 OcclusionQuery *query = occlusionQueries.top();
00317 occlusionQueries.pop();
00318
00319 query->BeginQuery();
00320 RenderBox(*info.node->GetAABB());
00321 query->EndQuery();
00322
00323 glPopAttrib();
00324
00325 queryQueue.push(QueryInfo(query, info));
00326
00327
00328
00329
00330
00331 if (info.node->IsLeaf() &&
00332 nodeInfo[info.node->id].lastVisibleFrame == frame-1) {
00333
00334 ProcessNode(info, cameraPos, planeMask, blendedNodes, nodeStack);
00335 }
00336 } else
00337 ProcessNode(info, cameraPos, planeMask, blendedNodes, nodeStack);
00338 }
00339 } else
00340 ProcessNode(info, cameraPos, planeMask, blendedNodes, nodeStack);
00341
00342
00343
00344
00345
00346 }
00347 }
00348
00349
00350 if (blendedNodes.size()) {
00351 glEnable(GL_BLEND);
00352 for (int i = blendedNodes.size()-1; i >=0; i--) {
00353 renderedBlendedNodes++;
00354
00355 DrawNode(blendedNodes[i]);
00356 }
00357 glDisable(GL_BLEND);
00358 }
00359
00360
00361
00362 LOG(wxString::Format(wxT("Opaque nodes: %i"), renderedNodes));
00363 LOG(wxString::Format(wxT("Blended nodes: %i"), renderedBlendedNodes));
00364 LOG(wxString::Format(wxT("Queried nodes: %i"), queriedNodes));
00365
00366
00367 scene = (Scene *)NULL;
00368 }
00369
00370
00371 void
00372 ChcRenderer::ProcessNode(NodeInfo &info,
00373 const VECTOR3 &cameraPos,
00374 const int planeMask,
00375 vector<const GeometryNode *> &blendedNodes,
00376 priority_queue< NodeInfo > &nodeStack
00377 )
00378 {
00379
00380
00381
00382
00383 if (info.node->IsLeaf()) {
00384 const GeometryNode * sceneNode =
00385 (const GeometryNode *)scene->GetNode(info.node->GetSceneNodeID());
00386
00387 const Material * material =
00388 scene->GetMaterial(sceneNode->GetMaterialID());
00389
00390 if (material && material->flags & Material::BLENDED)
00391 blendedNodes.push_back(sceneNode);
00392 else {
00393 renderedNodes++;
00394
00395 DrawNode(sceneNode);
00396 }
00397
00398 } else {
00399 nodeStack.push( NodeInfo(planeMask,
00400 (BVHNode *)info.node->GetLChild(),
00401 -SqrDistance(cameraPos,
00402 info.node->GetLChild()->GetAABB()->Center())));
00403 nodeStack.push( NodeInfo(planeMask,
00404 (BVHNode *)info.node->GetRChild(),
00405 -SqrDistance(cameraPos,
00406 info.node->GetRChild()->GetAABB()->Center())));
00407 }
00408 }
00409
00410 void
00411 ChcRenderer::PullUpVisibility(BVHNode *node)
00412 {
00413 while (node && nodeInfo[node->id].lastVisibleFrame != frame) {
00414 nodeInfo[node->id].lastVisibleFrame = frame;
00415 node = node->GetParent();
00416 }
00417 }
00418
00419 void
00420 ChcRenderer::PullUpInvisibility(BVHNode *node)
00421 {
00422 nodeInfo[node->id].lastVisibleFrame = frame-1;
00423 BVHNode *n = node->GetParent();
00424 while (n) {
00425 if (nodeInfo[n->GetLChild()->id].lastVisibleFrame != frame &&
00426 nodeInfo[n->GetRChild()->id].lastVisibleFrame != frame
00427 )
00428 nodeInfo[n->id].lastVisibleFrame = frame-1;
00429 else
00430 break;
00431 n = n->GetParent();
00432 }
00433 }