[502] | 1 | #include "Mesh.h" |
---|
| 2 | #include "GlRenderer.h" |
---|
| 3 | #include "ViewCellsManager.h" |
---|
| 4 | #include "SceneGraph.h" |
---|
| 5 | #include "Pvs.h" |
---|
| 6 | #include "Viewcell.h" |
---|
[507] | 7 | #include "Beam.cpp" |
---|
[502] | 8 | |
---|
| 9 | #include <GL/glext.h> |
---|
| 10 | |
---|
| 11 | GlRendererWidget *rendererWidget = NULL; |
---|
| 12 | |
---|
| 13 | #ifdef _WIN32 |
---|
| 14 | PFNGLGENOCCLUSIONQUERIESNVPROC glGenOcclusionQueriesNV; |
---|
| 15 | PFNGLBEGINOCCLUSIONQUERYNVPROC glBeginOcclusionQueryNV; |
---|
| 16 | PFNGLENDOCCLUSIONQUERYNVPROC glEndOcclusionQueryNV; |
---|
| 17 | PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV; |
---|
| 18 | #endif |
---|
| 19 | |
---|
| 20 | GlRenderer::GlRenderer(SceneGraph *sceneGraph, |
---|
| 21 | ViewCellsManager *viewCellsManager): |
---|
| 22 | Renderer(sceneGraph, viewCellsManager) |
---|
| 23 | { |
---|
| 24 | mSceneGraph->CollectObjects(&mObjects); |
---|
| 25 | mViewPoint = mSceneGraph->GetBox().Center(); |
---|
| 26 | mViewDirection = Vector3(0,0,1); |
---|
| 27 | // timerId = startTimer(10); |
---|
| 28 | mFrame = 0; |
---|
| 29 | mWireFrame = false; |
---|
| 30 | } |
---|
| 31 | |
---|
| 32 | GlRenderer::~GlRenderer() |
---|
| 33 | { |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | void |
---|
| 37 | GlRenderer::RenderIntersectable(Intersectable *object) |
---|
| 38 | { |
---|
| 39 | |
---|
| 40 | SetupFalseColor(object->mId); |
---|
| 41 | |
---|
| 42 | switch (object->Type()) { |
---|
| 43 | case Intersectable::MESH_INSTANCE: |
---|
| 44 | RenderMeshInstance((MeshInstance *)object); |
---|
| 45 | break; |
---|
| 46 | default: |
---|
| 47 | cerr<<"Rendering this object not yet implemented\n"; |
---|
| 48 | break; |
---|
| 49 | } |
---|
| 50 | } |
---|
| 51 | |
---|
| 52 | |
---|
| 53 | void |
---|
| 54 | GlRenderer::RenderMeshInstance(MeshInstance *mi) |
---|
| 55 | { |
---|
| 56 | RenderMesh(mi->GetMesh()); |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | void |
---|
| 60 | GlRenderer::SetupFalseColor(const int id) |
---|
| 61 | { |
---|
| 62 | // swap bits of the color |
---|
| 63 | |
---|
| 64 | glColor3ub(id&255, (id>>8)&255, (id>>16)&255); |
---|
| 65 | } |
---|
| 66 | |
---|
| 67 | void |
---|
| 68 | GlRenderer::SetupMaterial(Material *m) |
---|
| 69 | { |
---|
| 70 | if (m) |
---|
| 71 | glColor3fv(&(m->mDiffuseColor.r)); |
---|
| 72 | else |
---|
| 73 | glColor3f(1.0f, 1.0f, 1.0f); |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | void |
---|
| 77 | GlRenderer::RenderMesh(Mesh *mesh) |
---|
| 78 | { |
---|
| 79 | int i = 0; |
---|
| 80 | |
---|
| 81 | if (!mUseFalseColors) |
---|
| 82 | SetupMaterial(mesh->mMaterial); |
---|
| 83 | |
---|
| 84 | for (i=0; i < mesh->mFaces.size(); i++) { |
---|
| 85 | if (mWireFrame) |
---|
[504] | 86 | glBegin(GL_LINE_LOOP); |
---|
| 87 | else |
---|
[502] | 88 | glBegin(GL_POLYGON); |
---|
| 89 | |
---|
| 90 | Face *face = mesh->mFaces[i]; |
---|
| 91 | for (int j = 0; j < face->mVertexIndices.size(); j++) { |
---|
| 92 | glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x); |
---|
| 93 | } |
---|
| 94 | glEnd(); |
---|
| 95 | } |
---|
| 96 | } |
---|
| 97 | |
---|
| 98 | void |
---|
| 99 | GlRenderer::InitGL() |
---|
| 100 | { |
---|
| 101 | glMatrixMode(GL_PROJECTION); |
---|
| 102 | glLoadIdentity(); |
---|
| 103 | |
---|
| 104 | glMatrixMode(GL_MODELVIEW); |
---|
| 105 | glLoadIdentity(); |
---|
| 106 | |
---|
| 107 | glEnable(GL_CULL_FACE); |
---|
| 108 | glShadeModel(GL_FLAT); |
---|
| 109 | glEnable(GL_DEPTH_TEST); |
---|
| 110 | glEnable(GL_CULL_FACE); |
---|
| 111 | |
---|
| 112 | glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC) |
---|
| 113 | wglGetProcAddress("glGenOcclusionQueriesNV"); |
---|
| 114 | glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC) |
---|
| 115 | wglGetProcAddress("glBeginOcclusionQueryNV"); |
---|
| 116 | glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC) |
---|
| 117 | wglGetProcAddress("glEndOcclusionQueryNV"); |
---|
| 118 | glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC) |
---|
| 119 | wglGetProcAddress("glGetOcclusionQueryuivNV"); |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | |
---|
| 123 | |
---|
| 124 | void |
---|
| 125 | GlRenderer::SetupProjection(const int w, const int h) |
---|
| 126 | { |
---|
| 127 | glViewport(0, 0, w, h); |
---|
| 128 | glMatrixMode(GL_PROJECTION); |
---|
| 129 | glLoadIdentity(); |
---|
| 130 | gluPerspective(70.0, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal())); |
---|
| 131 | glMatrixMode(GL_MODELVIEW); |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | void |
---|
| 135 | GlRenderer::SetupCamera() |
---|
| 136 | { |
---|
| 137 | Vector3 target = mViewPoint + mViewDirection; |
---|
| 138 | Vector3 up(0,1,0); |
---|
| 139 | |
---|
| 140 | glLoadIdentity(); |
---|
| 141 | gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z, |
---|
| 142 | target.x, target.y, target.z, |
---|
| 143 | up.x, up.y, up.z); |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | void |
---|
| 147 | GlRenderer::RandomViewPoint() |
---|
| 148 | { |
---|
| 149 | Vector3 pVector = Vector3(halton.GetNumber(1), |
---|
| 150 | halton.GetNumber(2), |
---|
| 151 | halton.GetNumber(3)); |
---|
| 152 | |
---|
| 153 | Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4), |
---|
| 154 | M_PI*halton.GetNumber(5), |
---|
| 155 | 0.0f); |
---|
| 156 | |
---|
| 157 | mViewPoint = mSceneGraph->GetBox().GetPoint(pVector); |
---|
| 158 | |
---|
| 159 | mViewDirection = Normalize(Vector3(sin(dVector.x), |
---|
| 160 | // cos(dVector.y), |
---|
| 161 | 0.0f, |
---|
| 162 | cos(dVector.x))); |
---|
| 163 | |
---|
| 164 | halton.GenerateNext(); |
---|
| 165 | } |
---|
| 166 | |
---|
| 167 | |
---|
| 168 | float |
---|
| 169 | GlRenderer::GetPixelError() |
---|
| 170 | { |
---|
| 171 | float pErrorPixels = -1.0f; |
---|
| 172 | |
---|
| 173 | glReadBuffer(GL_BACK); |
---|
| 174 | |
---|
| 175 | mUseFalseColors = true; |
---|
| 176 | |
---|
| 177 | SetupCamera(); |
---|
| 178 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
| 179 | glEnable( GL_CULL_FACE ); |
---|
| 180 | |
---|
| 181 | RenderScene(); |
---|
| 182 | |
---|
| 183 | // now check whether any backfacing polygon would pass the depth test |
---|
| 184 | static int query = -1; |
---|
| 185 | if (query == -1) |
---|
| 186 | glGenOcclusionQueriesNV(1, (unsigned int *)&query); |
---|
| 187 | |
---|
| 188 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
---|
| 189 | glDepthMask(GL_FALSE); |
---|
| 190 | glDisable( GL_CULL_FACE ); |
---|
| 191 | |
---|
| 192 | glBeginOcclusionQueryNV(query); |
---|
| 193 | |
---|
| 194 | RenderScene(); |
---|
| 195 | |
---|
| 196 | glEndOcclusionQueryNV(); |
---|
| 197 | |
---|
| 198 | // at this point, if possible, go and do some other computation |
---|
| 199 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
---|
| 200 | glDepthMask(GL_TRUE); |
---|
| 201 | glEnable( GL_CULL_FACE ); |
---|
| 202 | |
---|
| 203 | unsigned int pixelCount; |
---|
| 204 | // reenable other state |
---|
| 205 | glGetOcclusionQueryuivNV(query, |
---|
| 206 | GL_PIXEL_COUNT_NV, |
---|
| 207 | &pixelCount); |
---|
| 208 | |
---|
| 209 | if (pixelCount > 0) |
---|
| 210 | return -1.0f; // backfacing polygon found -> not a valid viewspace sample |
---|
| 211 | |
---|
| 212 | ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint); |
---|
| 213 | |
---|
| 214 | if (viewcell) { |
---|
| 215 | SetupCamera(); |
---|
| 216 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
| 217 | |
---|
| 218 | // Render PVS |
---|
| 219 | std::map<Intersectable *, |
---|
| 220 | PvsData<Intersectable *>, |
---|
| 221 | LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin(); |
---|
| 222 | |
---|
| 223 | for (; it != viewcell->GetPvs().mEntries.end(); ++ it) { |
---|
| 224 | Intersectable *object = (*it).first; |
---|
| 225 | RenderIntersectable(object); |
---|
| 226 | } |
---|
| 227 | |
---|
| 228 | glBeginOcclusionQueryNV(query); |
---|
| 229 | |
---|
| 230 | SetupCamera(); |
---|
| 231 | |
---|
| 232 | RenderScene(); |
---|
| 233 | |
---|
| 234 | glEndOcclusionQueryNV(); |
---|
| 235 | |
---|
| 236 | |
---|
| 237 | unsigned int pixelCount; |
---|
| 238 | // reenable other state |
---|
| 239 | glGetOcclusionQueryuivNV(query, |
---|
| 240 | GL_PIXEL_COUNT_NV, |
---|
| 241 | &pixelCount); |
---|
| 242 | |
---|
| 243 | pErrorPixels = (100.f*pixelCount)/(GetWidth()*GetHeight()); |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | return pErrorPixels; |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | |
---|
| 250 | float |
---|
| 251 | GlRendererWidget::RenderErrors() |
---|
| 252 | { |
---|
| 253 | float pErrorPixels = -1.0f; |
---|
| 254 | |
---|
| 255 | glReadBuffer(GL_BACK); |
---|
| 256 | |
---|
| 257 | mUseFalseColors = true; |
---|
| 258 | |
---|
| 259 | SetupCamera(); |
---|
| 260 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
| 261 | glEnable( GL_CULL_FACE ); |
---|
| 262 | |
---|
| 263 | ObjectContainer::const_iterator oi = mObjects.begin(); |
---|
| 264 | for (; oi != mObjects.end(); oi++) |
---|
| 265 | RenderIntersectable(*oi); |
---|
| 266 | |
---|
| 267 | ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint); |
---|
| 268 | |
---|
| 269 | QImage im1, im2; |
---|
| 270 | QImage diff; |
---|
| 271 | |
---|
| 272 | if (viewcell) { |
---|
| 273 | // read back the texture |
---|
| 274 | im1 = grabFrameBuffer(true); |
---|
| 275 | |
---|
| 276 | SetupCamera(); |
---|
| 277 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
| 278 | |
---|
| 279 | std::map<Intersectable *, |
---|
| 280 | PvsData<Intersectable *>, |
---|
| 281 | LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin(); |
---|
| 282 | |
---|
| 283 | for (; it != viewcell->GetPvs().mEntries.end(); ++ it) { |
---|
| 284 | Intersectable *object = (*it).first; |
---|
| 285 | RenderIntersectable(object); |
---|
| 286 | } |
---|
| 287 | |
---|
| 288 | // read back the texture |
---|
| 289 | im2 = grabFrameBuffer(true); |
---|
| 290 | |
---|
| 291 | diff = im1; |
---|
| 292 | int x, y; |
---|
| 293 | int errorPixels = 0; |
---|
| 294 | |
---|
| 295 | for (y = 0; y < im1.height(); y++) |
---|
| 296 | for (x = 0; x < im1.width(); x++) |
---|
| 297 | if (im1.pixel(x, y) == im2.pixel(x, y)) |
---|
| 298 | diff.setPixel(x, y, qRgba(0,0,0,0)); |
---|
| 299 | else { |
---|
| 300 | diff.setPixel(x, y, qRgba(255,128,128,255)); |
---|
| 301 | errorPixels++; |
---|
| 302 | } |
---|
| 303 | pErrorPixels = (100.f*errorPixels)/(im1.height()*im1.width()); |
---|
| 304 | } |
---|
| 305 | |
---|
| 306 | // now render the pvs again |
---|
| 307 | SetupCamera(); |
---|
| 308 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
| 309 | mUseFalseColors = false; |
---|
| 310 | |
---|
| 311 | oi = mObjects.begin(); |
---|
| 312 | for (; oi != mObjects.end(); oi++) |
---|
| 313 | RenderIntersectable(*oi); |
---|
| 314 | |
---|
| 315 | // now render im1 |
---|
| 316 | if (viewcell) { |
---|
| 317 | if (mTopView) { |
---|
| 318 | mWireFrame = true; |
---|
| 319 | RenderMeshInstance(viewcell); |
---|
| 320 | mWireFrame = false; |
---|
| 321 | } |
---|
| 322 | |
---|
| 323 | // init ortographic projection |
---|
| 324 | glMatrixMode(GL_PROJECTION); |
---|
| 325 | glPushMatrix(); |
---|
| 326 | |
---|
| 327 | glLoadIdentity(); |
---|
| 328 | gluOrtho2D(0, 1.0f, 0, 1.0f); |
---|
| 329 | |
---|
| 330 | glMatrixMode(GL_MODELVIEW); |
---|
| 331 | glLoadIdentity(); |
---|
| 332 | |
---|
| 333 | bindTexture(diff); |
---|
| 334 | |
---|
| 335 | glPushAttrib(GL_ENABLE_BIT); |
---|
| 336 | glEnable( GL_ALPHA_TEST ); |
---|
| 337 | glDisable( GL_CULL_FACE ); |
---|
| 338 | glAlphaFunc( GL_GREATER, 0.5 ); |
---|
| 339 | |
---|
| 340 | glEnable( GL_TEXTURE_2D ); |
---|
| 341 | glBegin(GL_QUADS); |
---|
| 342 | |
---|
| 343 | glTexCoord2f(0,0); |
---|
| 344 | glVertex3f(0,0,0); |
---|
| 345 | |
---|
| 346 | glTexCoord2f(1,0); |
---|
| 347 | glVertex3f( 1, 0, 0); |
---|
| 348 | |
---|
| 349 | glTexCoord2f(1,1); |
---|
| 350 | glVertex3f( 1, 1, 0); |
---|
| 351 | |
---|
| 352 | glTexCoord2f(0,1); |
---|
| 353 | glVertex3f(0, 1, 0); |
---|
| 354 | glEnd(); |
---|
| 355 | |
---|
| 356 | glPopAttrib(); |
---|
| 357 | |
---|
| 358 | // restore the projection matrix |
---|
| 359 | glMatrixMode(GL_PROJECTION); |
---|
| 360 | glPopMatrix(); |
---|
| 361 | glMatrixMode(GL_MODELVIEW); |
---|
| 362 | } |
---|
| 363 | |
---|
| 364 | return pErrorPixels; |
---|
| 365 | } |
---|
| 366 | |
---|
| 367 | |
---|
| 368 | bool |
---|
| 369 | GlRenderer::RenderScene() |
---|
| 370 | { |
---|
| 371 | static int glList = -1; |
---|
| 372 | if (glList != -1) { |
---|
| 373 | glCallList(glList); |
---|
| 374 | } else { |
---|
| 375 | glList = glGenLists(1); |
---|
| 376 | glNewList(glList, GL_COMPILE_AND_EXECUTE); |
---|
| 377 | ObjectContainer::const_iterator oi = mObjects.begin(); |
---|
| 378 | for (; oi != mObjects.end(); oi++) |
---|
| 379 | RenderIntersectable(*oi); |
---|
| 380 | glEndList(); |
---|
| 381 | } |
---|
| 382 | return true; |
---|
| 383 | } |
---|
| 384 | |
---|
| 385 | |
---|
| 386 | void |
---|
| 387 | GlRendererBuffer::ClearErrorBuffer() |
---|
| 388 | { |
---|
| 389 | for (int i=0; i < mPvsStatFrames; i++) { |
---|
| 390 | mPvsErrorBuffer[i] = 1.0f; |
---|
| 391 | } |
---|
| 392 | } |
---|
| 393 | |
---|
| 394 | |
---|
| 395 | void |
---|
| 396 | GlRendererBuffer::EvalPvsStat() |
---|
| 397 | { |
---|
| 398 | mPvsStat.Reset(); |
---|
| 399 | halton.Reset(); |
---|
| 400 | |
---|
| 401 | makeCurrent(); |
---|
| 402 | SetupProjection(GetWidth(), GetHeight()); |
---|
| 403 | |
---|
| 404 | for (int i=0; i < mPvsStatFrames; i++) { |
---|
| 405 | float err; |
---|
| 406 | RandomViewPoint(); |
---|
| 407 | if (mPvsErrorBuffer[i] > 0.0f) { |
---|
| 408 | mPvsErrorBuffer[i] = GetPixelError(); |
---|
| 409 | cout<<"("<<i<<","<<mPvsErrorBuffer[i]<<")"; |
---|
| 410 | // swapBuffers(); |
---|
| 411 | } |
---|
| 412 | |
---|
| 413 | err = mPvsErrorBuffer[i]; |
---|
| 414 | |
---|
| 415 | if (err >= 0.0f) { |
---|
| 416 | if (err > mPvsStat.maxError) |
---|
| 417 | mPvsStat.maxError = err; |
---|
| 418 | mPvsStat.sumError += err; |
---|
| 419 | if (err == 0.0f) |
---|
| 420 | mPvsStat.errorFreeFrames++; |
---|
| 421 | mPvsStat.frames++; |
---|
| 422 | } |
---|
| 423 | } |
---|
| 424 | |
---|
| 425 | doneCurrent(); |
---|
| 426 | |
---|
| 427 | cout<<endl<<flush; |
---|
| 428 | mRenderingFinished.wakeAll(); |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | |
---|
| 432 | |
---|
| 433 | |
---|
| 434 | |
---|
| 435 | void |
---|
| 436 | GlRendererWidget::mousePressEvent(QMouseEvent *e) |
---|
| 437 | { |
---|
| 438 | int x = e->pos().x(); |
---|
| 439 | int y = e->pos().y(); |
---|
| 440 | |
---|
| 441 | mousePoint.x = x; |
---|
| 442 | mousePoint.y = y; |
---|
| 443 | |
---|
| 444 | } |
---|
| 445 | |
---|
| 446 | void |
---|
| 447 | GlRendererWidget::mouseMoveEvent(QMouseEvent *e) |
---|
| 448 | { |
---|
| 449 | float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3; |
---|
| 450 | float TURN_SENSITIVITY=0.1f; |
---|
| 451 | float TILT_SENSITIVITY=32.0 ; |
---|
| 452 | float TURN_ANGLE= M_PI/36.0 ; |
---|
| 453 | |
---|
| 454 | int x = e->pos().x(); |
---|
| 455 | int y = e->pos().y(); |
---|
| 456 | |
---|
| 457 | if (e->modifiers() & Qt::ControlModifier) { |
---|
| 458 | mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0; |
---|
| 459 | mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0; |
---|
| 460 | } else { |
---|
| 461 | mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY); |
---|
| 462 | float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY; |
---|
| 463 | float angle = atan2(mViewDirection.x, mViewDirection.z); |
---|
| 464 | mViewDirection.x = sin(angle+adiff); |
---|
| 465 | mViewDirection.z = cos(angle+adiff); |
---|
| 466 | } |
---|
| 467 | |
---|
| 468 | mousePoint.x = x; |
---|
| 469 | mousePoint.y = y; |
---|
| 470 | |
---|
| 471 | updateGL(); |
---|
| 472 | } |
---|
| 473 | |
---|
| 474 | void |
---|
| 475 | GlRendererWidget::mouseReleaseEvent(QMouseEvent *) |
---|
| 476 | { |
---|
| 477 | |
---|
| 478 | |
---|
| 479 | } |
---|
| 480 | |
---|
| 481 | void |
---|
| 482 | GlRendererWidget::resizeGL(int w, int h) |
---|
| 483 | { |
---|
| 484 | SetupProjection(w, h); |
---|
| 485 | updateGL(); |
---|
| 486 | } |
---|
| 487 | |
---|
| 488 | void |
---|
| 489 | GlRendererWidget::paintGL() |
---|
| 490 | { |
---|
| 491 | RenderErrors(); |
---|
| 492 | mFrame++; |
---|
| 493 | } |
---|
| 494 | |
---|
| 495 | |
---|
| 496 | void |
---|
| 497 | GlRendererWidget::SetupCamera() |
---|
| 498 | { |
---|
| 499 | if (!mTopView) |
---|
| 500 | GlRenderer::SetupCamera(); |
---|
| 501 | else { |
---|
| 502 | float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05; |
---|
| 503 | Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x, |
---|
[504] | 504 | -1, |
---|
[502] | 505 | mViewDirection.y); |
---|
| 506 | |
---|
| 507 | Vector3 target = mViewPoint + dist*mViewDirection; |
---|
| 508 | Vector3 up(0,1,0); |
---|
| 509 | |
---|
| 510 | glLoadIdentity(); |
---|
[504] | 511 | gluLookAt(pos.x, pos.y, pos.z, |
---|
[502] | 512 | target.x, target.y, target.z, |
---|
| 513 | up.x, up.y, up.z); |
---|
| 514 | } |
---|
| 515 | |
---|
| 516 | } |
---|
[504] | 517 | |
---|
| 518 | void |
---|
| 519 | GlRendererWidget::keyPressEvent ( QKeyEvent * e ) |
---|
| 520 | { |
---|
| 521 | switch (e->key()) { |
---|
| 522 | case Qt::Key_T: |
---|
| 523 | mTopView = !mTopView; |
---|
| 524 | updateGL(); |
---|
| 525 | break; |
---|
| 526 | default: |
---|
| 527 | e->ignore(); |
---|
| 528 | break; |
---|
| 529 | } |
---|
| 530 | |
---|
| 531 | } |
---|
[507] | 532 | |
---|
| 533 | |
---|
| 534 | void |
---|
| 535 | GlRendererBuffer::SampleBeamContributions( |
---|
| 536 | Intersectable *sourceObject, |
---|
| 537 | Beam &beam, |
---|
| 538 | const int desiredSamples, |
---|
| 539 | BeamSampleStatistics &stat |
---|
| 540 | ) |
---|
| 541 | { |
---|
| 542 | // assumes that the beam is constructed and contains kd-tree nodes |
---|
| 543 | // and viewcells which it intersects |
---|
| 544 | |
---|
| 545 | |
---|
| 546 | |
---|
| 547 | |
---|
| 548 | // Get the number of viewpoints to be sampled |
---|
| 549 | // Now it is a sqrt but in general a wiser decision could be made. |
---|
| 550 | // The less viewpoints the better for rendering performance, since less passes |
---|
| 551 | // over the beam is needed. |
---|
| 552 | // The viewpoints could actually be generated outside of the bounding box which |
---|
| 553 | // would distribute the 'efective viewpoints' of the object surface and thus |
---|
| 554 | // with a few viewpoints better sample the vipoint space.... |
---|
| 555 | |
---|
| 556 | int viewPointSamples = sqrt((float)desiredSamples); |
---|
| 557 | |
---|
| 558 | // the number of direction samples per pass is given by the number of viewpoints |
---|
| 559 | int directionalSamples = desiredSamples/viewPointSamples; |
---|
| 560 | int i; |
---|
| 561 | for (i=0; i < viewPointSamples; i++) { |
---|
| 562 | Vector3 viewPoint = beam.mBox.GetRandomPoint(); |
---|
| 563 | // perhaps the viewpoint should be shifted back a little bit so that it always lies |
---|
| 564 | // inside the source object |
---|
| 565 | // 'ideally' the viewpoints would be distributed on the soureObject surface, but this |
---|
| 566 | // would require more complicated sampling (perhaps hierarchical rejection sampling of |
---|
| 567 | // the object surface is an option here - only the mesh faces which are inside the box |
---|
| 568 | // are considered as candidates) |
---|
| 569 | SampleViewpointContributions( |
---|
| 570 | sourceObject, |
---|
| 571 | beam, |
---|
| 572 | directionalSamples, |
---|
| 573 | stat |
---|
| 574 | ); |
---|
| 575 | } |
---|
| 576 | |
---|
| 577 | |
---|
| 578 | // note: |
---|
| 579 | // this routine would be called only if the number of desired samples is sufficiently |
---|
| 580 | // large - for other rss tree cells the cpu based sampling is perhaps more efficient |
---|
| 581 | // distributing the work between cpu and gpu would also allow us to place more sophisticated |
---|
| 582 | // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU |
---|
| 583 | // in order that thios scheme is working well the gpu render buffer should run in a separate |
---|
| 584 | // thread than the cpu sampler, which would not be such a big problem.... |
---|
| 585 | } |
---|
| 586 | |
---|
| 587 | |
---|
| 588 | void |
---|
| 589 | GlRendererBuffer::SampleViewpointContributions( |
---|
| 590 | Intersectable *sourceObject, |
---|
| 591 | Beam &beam, |
---|
| 592 | const int desiredSamples, |
---|
| 593 | BeamSampleStatistics &stat |
---|
| 594 | ) |
---|
| 595 | { |
---|
| 596 | // 1. setup the view port to match the desired samples |
---|
| 597 | // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox |
---|
| 598 | |
---|
| 599 | // 3. reset z-buffer to 0 and render the source object for the beam using |
---|
| 600 | // glDepthFunc(GL_GREATER) |
---|
| 601 | // and glCullFace(Enabled) and glFrontFace(GL_CW) |
---|
| 602 | // remember the ray origin depth buffer somewhere? |
---|
| 603 | |
---|
| 604 | // 4. set back to normal rendering and clear the ray termination depth buffer |
---|
| 605 | // 5. render all objects inside the beam using id based false color |
---|
| 606 | // (objects can be compiled to a gl list now so that subsequent rendering for |
---|
| 607 | // this beam is fast - the same hold for step 3) |
---|
| 608 | |
---|
| 609 | |
---|
| 610 | // 6. Now we have a two depth buffers defining the ray origin and termination |
---|
| 611 | // only rays which have non-zero entry in the origin buffer are valid since |
---|
| 612 | // they realy start on the object surface (this can also be tagged by setting a |
---|
| 613 | // stencil buffer bit at step 3) |
---|
| 614 | |
---|
| 615 | // 7. Use occlusion queries for all viewcell meshes associated with the beam -> |
---|
| 616 | // a fragment passes if the corresponding stencil fragment is set and its depth is |
---|
| 617 | // between origin and termination buffer |
---|
| 618 | |
---|
| 619 | // 8. The number of visible pixels is the number of sample rays which see the source |
---|
| 620 | // object from the corresponding viewcell -> rember these values for later update |
---|
| 621 | // of the viewcell pvs - or update immediatelly? |
---|
| 622 | |
---|
| 623 | // In general it is not neccessary to rember to extract all the rays cast. I hope it |
---|
| 624 | // would be sufficient to gain only the intergral statistics about the new contributions |
---|
| 625 | // and so the rss tree would actually store no new rays (only the initial ones) |
---|
| 626 | // the subdivision of the tree would only be driven by the statistics (the glrender could |
---|
| 627 | // evaluate the contribution entropy for example) |
---|
| 628 | // However might be an option to extract/store only those the rays which made a contribution |
---|
| 629 | // (new viewcell has been discovered) or relative contribution greater than a threashold... |
---|
| 630 | |
---|
| 631 | |
---|
| 632 | } |
---|