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