#include "glInterface.h" #include "QtGlRenderer.h" #include "Mesh.h" #include "OcclusionQuery.h" #include "ViewCellsManager.h" #include "SceneGraph.h" #include "Pvs.h" #include "Viewcell.h" #include "Beam.h" #include "KdTree.h" #include "Environment.h" #include "RssPreprocessor.h" #include "RssTree.h" #include "Trackball.h" #include "QtPreprocessorThread.h" #include "Material.h" #include "IntersectableWrapper.h" #include "LogWriter.h" #include "RayCaster.h" #include "ObjectPlacer.h" #define TEASER 1 #define USE_CG 1 #define TEST_PVS_RENDERING 0 #if USE_CG #include #include #endif #include using namespace std; namespace GtpVisibilityPreprocessor { class ViewCellsManager; static CGcontext sCgContext = NULL; static CGprogram sCgFragmentProgram = NULL; static CGprofile sCgFragmentProfile; QtGlRendererWidget *rendererWidget = NULL; QtGlDebuggerWidget *debuggerWidget = NULL; static SimpleRayContainer sViewPointsList; static SimpleRayContainer::const_iterator sViewPointsListIt; static int sCurrentSamples = 0; static int sNextSamplesThreshold[] = {10000000, 50000000, 100000000, 250000000}; //static int sNextSamplesThreshold[] = {100000000, 200000000}; static int sNumReplays = 4; static int sCurrentSamplesThreshold = 0; void processHits (GLint hits, GLuint buffer[]) { unsigned int i, j; GLuint names, *ptr; cout << "hits: " << hits << endl;; ptr = (GLuint *) buffer; for (i = 0; i < hits; i++) { /* for each hit */ names = *ptr; printf ("number of names for hit: %d\n", names); ptr ++; printf("z1: %g;", (float) *ptr / 0x7fffffff); ptr ++; printf("z2: %g\n", (float) *ptr / 0x7fffffff); ptr ++; printf ("the name is "); // for each name for (j = 0; j < names; j++) printf ("%d ", *ptr); ptr++; printf ("\n"); } } static inline bool ilt(Intersectable *obj1, Intersectable *obj2) { return obj1->mId < obj2->mId; } inline static bool nearerThan(ViewCell *vc1, ViewCell *vc2) { return vc1->GetDistance() > vc2->GetDistance(); } #if USE_CG static void handleCgError() { Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl; exit(1); } #endif void QtGlRendererBuffer::MakeLive() { QGLPixelBuffer::makeCurrent(); //makeCurrent(); } void QtGlRendererBuffer::DoneLive() { QGLPixelBuffer::doneCurrent(); //doneCurrent(); } QtGlRendererBuffer::QtGlRendererBuffer(int w, int h, SceneGraph *sceneGraph, ViewCellsManager *viewcells, KdTree *tree): QGLPixelBuffer(QSize(w, h), QGLFormat(QGL::SampleBuffers) /*,| QGL::StencilBuffer | QGL::DepthBuffer | QGL::DoubleBuffer | QGL::Rgba) */), GlRendererBuffer(sceneGraph, viewcells, tree) { //makeCurrent(); MakeLive(); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -99, 99); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); InitGL(); //doneCurrent(); //DoneLive(); } void QtGlRendererBuffer::RenderPvs(const ObjectPvs &pvs) { EnableDrawArrays(); // prepare pvs for rendering PreparePvs(pvs); if (mUseVbos) glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId); int offset = (int)mObjects.size() * 3; char *arrayPtr = mUseVbos ? NULL : (char *)mData; glVertexPointer(3, GL_FLOAT, 0, (char *)arrayPtr); glNormalPointer(GL_FLOAT, 0, (char *)arrayPtr + offset * sizeof(Vector3)); glDrawElements(GL_TRIANGLES, mIndexBufferSize, GL_UNSIGNED_INT, mIndices); } void QtGlRendererBuffer::RenderTrianglePvs() { ObjectContainer::const_iterator oit, oit_end = mViewCellsManager->GetPreprocessor()->mTrianglePvs.end(); //int sz = mViewCellsManager->GetPreprocessor()->mDummyBuffer.size(); int i = 0; for (oit = mViewCellsManager->GetPreprocessor()->mTrianglePvs.begin(); oit != oit_end; ++ oit, ++ i) { //int dum = mViewCellsManager->GetPreprocessor()->mDummyBuffer[i]; //glColor3f(0, (float)dum / 20.0f, 1); if (mUseFalseColors) SetupFalseColor((*oit)->mId); RenderIntersectable(*oit); } } // reimplemented here so that we can snap the error windows float QtGlRendererBuffer::GetPixelError(int &pvsSize, int pass) { MakeLive(); if (0) { cout << "stencil: " << format().stencil() << endl; cout << "depth: " << format().depth() << endl; cout << "rgba: " << format().rgba() << endl; cout << "double: " << format().doubleBuffer() << endl; cout << "depth: " << format().depth() << endl; cout << "gl:" << format().hasOpenGL() << endl; cout << "dir:" << format().directRendering() << endl; } ++ mCurrentFrame; float pErrorPixels = -1.0f; mUseFalseColors = false; unsigned int pixelCount = 0; ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint); if (viewcell == NULL) return -1.0f; bool evaluateFilter; Environment::GetSingleton()->GetBoolValue("Preprocessor.evaluateFilter", evaluateFilter); ObjectPvs pvs; if (!evaluateFilter) pvs = viewcell->GetPvs(); else mViewCellsManager->ApplyFilter2(viewcell, false, mViewCellsManager->GetFilterWidth(), pvs); pvsSize = pvs.GetSize(); // hack: assume that view cell empty if (pvsSize == 0) return 0.0f; SetupCamera(); // use shading if (mSnapErrorFrames) { glEnable(GL_NORMALIZE); // mat_specular and mat_shininess are NOT default values GLfloat mat_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f}; GLfloat mat_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat mat_specular[] = {0.3f, 0.3f, 0.3f, 1.0f}; GLfloat mat_shininess[] = {1.0f}; glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); GLfloat light_ambient[] = {0.1, 0.1, 0.1, 1.0}; //GLfloat light_diffuse[] = {0.6, 0.6, 0.6, 1.0}; GLfloat light_diffuse[] = {0.5, 0.5, 0.5, 1.0}; GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0}; glEnable(GL_LIGHTING); GLfloat light_position[] = {0.f, 0.f, 0.f, 1.0f}; // lights in arena glEnable(GL_LIGHT0); // a light glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); GLfloat lmodel_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glShadeModel(GL_SMOOTH); } //glDisable(GL_ALPHA_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //glColor3f(0.6f, 0.6f, 0.6f); glColor3f(0, 1, 0); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glFrontFace(GL_CCW); glCullFace(GL_BACK); glStencilFunc(GL_EQUAL, 0x0, 0x1); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); KdNode::NewMail2(); Intersectable::NewMail(); // render pvs once RenderPvs(pvs); //cout << "rendered nodes: " << mRenderedNodes << endl; //glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_STENCIL_TEST); glColor3f(1, 0, 0); // render scene, record differences OcclusionQuery *query = mOcclusionQueries[0]; KdNode::NewMail2(); Intersectable::NewMail(); query->BeginQuery(); // current frame has to be increased at each rendering pass ++ mCurrentFrame; RenderScene(); glFlush(); query->EndQuery(); glDisable(GL_STENCIL_TEST); pixelCount = query->GetQueryResult(); pErrorPixels = (float)pixelCount / (GetWidth() * GetHeight()); const int pixelThres = 0; // some error happened if (pixelCount > pixelThres) { cout << "f " << mFrame << " id " << viewcell->GetId() << " pvs " << pvsSize << " e " << pixelCount << " vp " << mViewPoint << " vd " << mViewDirection << endl; if (mSnapErrorFrames) { glReadBuffer(GL_BACK); //glReadBuffer(GL_FRONT); ////////////// //-- output error visualization char filename[256]; //sprintf(filename, "error-frame-%04d-%05d.bmp", pass, mFrame); //sprintf(filename, "error-frame-%05d-%0.5f.png", mFrame, pErrorPixels); sprintf_s(filename, "error-frame-%05d-%04d-%08d.png", mFrame, viewcell->GetId(), pixelCount); QImage im = toImage(); string str = mSnapPrefix + filename; QString qstr(str.c_str()); im.save(qstr, "PNG"); if (0) { /////////// //-- output computed pvs //mUseFalseColors = false; mUseFalseColors = true; glPushAttrib(GL_CURRENT_BIT); glColor3f(0, 1, 0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); KdNode::NewMail2(); Intersectable::NewMail(); ++ mCurrentFrame; // render pvs once //RenderPvs(pvs); RenderTrianglePvs(); glFlush(); mUseFalseColors = false; im = toImage(); sprintf_s(filename, "error-frame-%04d-%04d-%08d-pvs.png", mFrame, viewcell->GetId(), pixelCount); str = mSnapPrefix + filename; qstr = str.c_str(); im.save(qstr, "PNG"); glPopAttrib(); } } } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); //DoneLive(); return pErrorPixels; } int QtGlRendererBuffer::ComputePvs(ObjectContainer &objects, ObjectContainer &pvs) const { int pvsSize = 0; QImage image = toImage(); Intersectable::NewMail(); std::stable_sort(objects.begin(), objects.end(), ilt); MeshInstance dummy(NULL); Intersectable *obj = NULL; for (int x = 0; x < image.width(); ++ x) { for (int y = 0; y < image.height(); ++ y) { QRgb pix = image.pixel(x, y); const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix)); dummy.SetId(id); ObjectContainer::iterator oit = lower_bound(objects.begin(), objects.end(), &dummy, ilt); if (//(oit != oit.end()) && ((*oit)->GetId() == id) && !obj->Mailed()) { obj = *oit; obj->Mail(); ++ pvsSize; pvs.push_back(obj); } } } return pvsSize; } void QtGlRendererWidget::InitGL() { GlRenderer::InitGL(); //glEnable(GL_FOG); //glFogi(GL_FOG_MODE, GL_EXP); //glFogf(GL_FOG_DENSITY, .2f); glFogi(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_START, 50.f); glFogf(GL_FOG_END, 500.f); // mat_specular and mat_shininess are NOT default values GLfloat mat_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; GLfloat mat_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat mat_specular[] = {0.3f, 0.3f, 0.3f, 1.0f}; GLfloat mat_shininess[] = {1.0f}; glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glEnable(GL_LIGHTING); // a light GLfloat light_ambient[] = {0.05, 0.05, 0.05, 1.0}; GLfloat light_diffuse[] = {0.7, 0.7, 0.7, 1.0}; GLfloat light_specular[] = {0.3, 0.3, 0.3, 1.0}; //GLfloat light_position[] = {0.f, .0f, 0.f, 1.0f}; //GLfloat light_position[] = {600.0f, 250.0f, -500.f, 1.0f}; //GLfloat light_position[] = {278.0f, 548.8f,279.0f, 1.0f}; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0); // GLfloat light1_position[] = {-22.076887, 21.070816, 50.272095}; // GLfloat light1_position[] = {0, 0, -100}; glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f); glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0); glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0); glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_LIGHT2); GLfloat lmodel_ambient[] = {0.05f, 0.05f, 0.05f, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); //glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); glEnable(GL_COLOR_MATERIAL); glShadeModel(GL_SMOOTH); } void QtGlRendererWidget::SetupCameraProjection(const int w, const int h, const float angle) { if (!mTopView) { int ww = w; int hh = h; glViewport(0, 0, ww, hh); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(angle, ww/(float)hh, 0.1, 2.0 * Magnitude(mSceneGraph->GetBox().Diagonal())); glMatrixMode(GL_MODELVIEW); } else { int ww = w; int hh = h; glViewport(0, 0, ww, hh); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50.0, ww / (float)hh, 0.1, 20.0 * Magnitude(mSceneGraph->GetBox().Diagonal())); glMatrixMode(GL_MODELVIEW); } } bool QtGlRendererWidget::PvsChanged(ViewCell *viewCell) const { if (viewCell != mPvsCache.mViewCell) return true; if (viewCell->GetPvs().GetSize() != mPvsCache.mUnfilteredPvsSize) return true; return false; } void QtGlRendererWidget::_RenderPvs() { EnableDrawArrays(); if (mUseVbos) glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId); mUseFalseColors = false; int offset = (int)mObjects.size() * 3; char *arrayPtr = mUseVbos ? NULL : (char *)mData; glVertexPointer(3, GL_FLOAT, 0, (char *)arrayPtr); glNormalPointer(GL_FLOAT, 0, (char *)arrayPtr + offset * sizeof(Vector3)); glDrawElements(GL_TRIANGLES, mIndexBufferSize, GL_UNSIGNED_INT, mIndices); // handle dynamic objects in pvss DynamicObjectsContainer::const_iterator dit, dit_end = mDynamicPvsObjects.end(); //cout << "dynamic objects in pvs " << mDynamicPvsObjects.size() << endl;; #if 0 for (dit = mDynamicPvsObjects.begin(); dit != dit_end; ++ dit) { _RenderDynamicObject(*dit); } #endif //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // show placed dynamic objects as wireframe Preprocessor *p = mViewCellsManager->GetPreprocessor(); dit_end = p->mDynamicObjects.end(); int i = 0; for (dit = p->mDynamicObjects.begin(); dit != dit_end; ++ dit, ++ i) { if (i == mCurrentDynamicObjectIdx) glColor3f(1, 0, 1); else glColor3f(0, 1, 0); _RenderDynamicObject(*dit); } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } void QtGlRendererWidget::PreparePvs(const ObjectPvs &pvs) { int indexBufferSize = 0; // hack: mail not working with multiple threads KdNode::NewMail2(); mPvsSize = pvs.GetSize(); mDynamicPvsObjects.clear(); ObjectPvsIterator it = pvs.GetIterator(); while (it.HasMoreEntries()) { Intersectable *obj = it.Next(); switch (obj->Type()) { case Intersectable::KD_INTERSECTABLE: { KdNode *node = static_cast(obj)->GetItem(); _UpdatePvsIndices(node, indexBufferSize); } break; case Intersectable::SCENEGRAPHLEAF_INTERSECTABLE: mDynamicPvsObjects.push_back(static_cast(obj)->GetItem()); break; default: cerr << "PreparePvs: type " << Intersectable::GetTypeName(obj) << " not handled yet" << endl; } } mIndexBufferSize = indexBufferSize; } void QtGlRendererWidget::VisualizePvs() { if (mUseVbos) glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId); ++ mCurrentFrame; EnableDrawArrays(); if (mDetectEmptyViewSpace) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); ViewCell *viewcell = NULL; viewcell = mViewCellsManager->GetViewCell(mViewPoint, true); if (viewcell) { // copy the pvs so that it can be filtered ... if (PvsChanged(viewcell)) { mPvsCache.Reset(); mPvsCache.mViewCell = viewcell; mPvsCache.mUnfilteredPvsSize = viewcell->GetPvs().GetSize(); if (mUseSpatialFilter) { //mMutex.lock(); // mSpatialFilter size is in range 0.001 - 0.1 mViewCellsManager->ApplyFilter2(viewcell, mUseFilter, 100.0f * mSpatialFilterSize, mPvsCache.mPvs, &mPvsCache.filteredBoxes); //mPvsCache.mPvs = pvs; //mMutex.unlock(); //cout << "pvs size: " << mPvsCache.mPvs.GetSize() << endl; } else { mPvsCache.mPvs = viewcell->GetPvs(); } // update the indices for rendering PreparePvs(mPvsCache.mPvs); emit PvsUpdated(); mCurrentPvsCost = mPvsCache.mPvs.EvalPvsCost(); } // Render PVS if (mUseSpatialFilter && mRenderBoxes) { for (size_t i=0; i < mPvsCache.filteredBoxes.size(); ++ i) { RenderBox(mPvsCache.filteredBoxes[i]); } } else { if (!mRenderVisibilityEstimates && !mUseRandomColorPerPvsObject) _RenderPvs(); else _RenderColoredPvs(); } if (mRenderFilter) { mWireFrame = true; RenderIntersectable(viewcell); mWireFrame = false; } } else { RenderScene(); } //cout << "vp: " << mViewPoint << " vd: " << mViewDirection << endl; } float QtGlRendererWidget::RenderErrors() { float pErrorPixels = -1.0f; SetupCamera(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glPushAttrib(GL_ENABLE_BIT); glStencilFunc(GL_EQUAL, 0x0, 0x1); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); #if TEASER glColor3f(0.0f, 0.8f, 0.0f); #else glColor3f(0.6f, 0.6f, 0.6f); #endif // Render PVS VisualizePvs(); glEnable(GL_STENCIL_TEST); glDisable(GL_LIGHTING); SetupCamera(); mUseForcedColors = true; glColor3f(1.0f, 0.0f, 0.0f); OcclusionQuery *query = mOcclusionQueries[0]; query->BeginQuery(); RenderScene(); mUseForcedColors = false; query->EndQuery(); glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glPopAttrib(); // reenable other state // int wait=0; // while (!query.ResultAvailable()) { // wait++; // } int pixelCount = query->GetQueryResult(); pErrorPixels = (float)pixelCount / (GetWidth() * GetHeight()); if (0) cout << "error pixels=" << pixelCount << endl; mRenderError = pErrorPixels; return pErrorPixels; } void QtGlRendererWidget::timerEvent(QTimerEvent *timerEvent) { if (mReplayMode && (timerEvent->timerId() == mReplayTimerId)) { if (sViewPointsListIt == sViewPointsList.end()) { cout << "stopping replay" << endl; mReplayMode = false; GetPreprocessor()->mSynchronize = false; } else { SimpleRay sray = *sViewPointsListIt; mViewPoint = sray.mOrigin; mViewDirection = sray.mDirection; ++ sViewPointsListIt; } updateGL(); // output the current frame buffer if (mExportFrameBuffer) { const int dist = sViewPointsListIt - sViewPointsList.begin(); char filename[200]; sprintf(filename, "error-frame-%04d-%05d.bmp", sCurrentSamples, dist); //QPixmap img = renderPixmap(0, 0, true); QImage im = grabFrameBuffer(); string str = mSnapPrefix + filename; QString qstr(str.c_str()); //im.save(qstr, "PNG"); // use bmp for lossless storage (for video) im.save(qstr, "BMP"); } } else if (timerEvent->timerId() == mUpdateTimerId) // update pvss from time to time update(); // grab frame buffer after a certain number of samples if (!mReplayMode && (sCurrentSamplesThreshold < sNumReplays) && ((GetPreprocessor()->mCurrentSamples > sNextSamplesThreshold[sCurrentSamplesThreshold]))) { ++ sCurrentSamplesThreshold; cout << "replaying at total samples: " << GetPreprocessor()->mCurrentSamples << endl; ReplayViewPoints(); } } void QtGlRendererWidget::mousePressEvent(QMouseEvent *e) { int x = e->pos().x(); int y = e->pos().y(); mousePoint.x = x; mousePoint.y = y; if (e->button() == Qt::RightButton) { if (mPlacer->GetCurrentObject()) { Vector3 pt = Unproject(x, y); mPlacer->PlaceObject(pt); SceneGraphLeaf *leaf = mPlacer->GetCurrentObject(); // hack: should just pass a IntersectableGroup as a whole // instead we duplicate the object container and create a new // leaf SceneGraphLeaf *newObj = new SceneGraphLeaf(*leaf); // make current object // the object is added at the end of the vector mCurrentDynamicObjectIdx = (int)GetPreprocessor()->mDynamicObjects.size(); GetPreprocessor()->RegisterDynamicObject(newObj); } } } void QtGlRendererWidget::mouseReleaseEvent(QMouseEvent *e) { int x = e->pos().x(); int y = e->pos().y(); mousePoint.x = x; mousePoint.y = y; if (e->modifiers() & Qt::ShiftModifier) { const Vector3 pt = Unproject(x, y); int idx = FindDynamicObject(x, y); if (idx >= 0) { mCurrentDynamicObjectIdx = idx; } } } void QtGlRendererWidget::mouseMoveEvent(QMouseEvent *e) { if (mReplayMode) return; float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3; float TURN_SENSITIVITY = 0.1f; float TILT_SENSITIVITY = 32.0 ; float TURN_ANGLE= M_PI / 36.0 ; int x = e->pos().x(); int y = e->pos().y(); int diffx = -(mousePoint.x - x); int diffy = -(mousePoint.y - y); const float t = 1.0f; if (e->modifiers() & Qt::ControlModifier) { mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY / 2.0; mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY / 2.0; } else if (e->modifiers() & Qt::AltModifier) { if (mCurrentDynamicObjectIdx >= 0) { Matrix4x4 tm; SceneGraphLeaf *l = mViewCellsManager->GetPreprocessor()->mDynamicObjects[mCurrentDynamicObjectIdx]; switch (mTrafoType) { case 0: { if (e->modifiers() & Qt::ShiftModifier) { const Vector3 transl(0, diffy, 0); tm = TranslationMatrix(transl); } else { const Vector3 transl(diffx, 0, diffy); tm = TranslationMatrix(transl); } } break; case 1: { float scalef = 1.0f + 0.01f * (diffx + diffy); if (scalef < 0.9) scalef = 0.9f; else if (scalef > 1.1f) scalef = 1.1f; tm = ScaleMatrix(scalef, scalef, scalef); } break; case 2: { // tm = RotationXMatrix(diffx) * RotationYMatrix(diffy); tm = RotationYMatrix(diffx); } break; default: cerr << "not implemented" << endl; } l->ApplyTransform(tm); updateGL(); } } else { mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY); float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY; float angle = atan2(mViewDirection.x, mViewDirection.z); mViewDirection.x = sin(angle + adiff); mViewDirection.z = cos(angle + adiff); } mousePoint.x = x; mousePoint.y = y; updateGL(); } void QtGlRendererWidget::resizeGL(int w, int h) { SetupCameraProjection(w, h); updateGL(); } void QtGlRendererWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetupCameraProjection(width(), height()); SetupCamera(); GLfloat light0_position[] = {22.495655, 21.070816, -1001.375000}; GLfloat light1_position[] = {-22.076887, 21.070816, -997.272095}; GLfloat light2_position[] = { 0.3, 1.5, -0.3, 0.0 }; glLightfv (GL_LIGHT0, GL_POSITION, light0_position); glLightfv (GL_LIGHT1, GL_POSITION, light1_position); glLightfv (GL_LIGHT2, GL_POSITION, light2_position); if (mRenderErrors) RenderErrors(); else { glColor3f(0.6f, 0.6f, 0.6f); VisualizePvs(); } if (mShowRays) RenderRays(mViewCellsManager->mVizBuffer.GetRays(), mRayVisualizationMethod, mShowDistribution, 1); RenderInfo(); ++ mFrame; // cout<<"vp="<ignore(); break; } } QtGlRendererWidget::QtGlRendererWidget( SceneGraph *sceneGraph, ViewCellsManager *viewcells, KdTree *tree, QWidget * parent, const QGLWidget * shareWidget, Qt::WFlags f): GlRendererWidget(sceneGraph, viewcells, tree), QGLWidget(QGLFormat(QGL::SampleBuffers), parent, shareWidget, f) { mPreprocessorThread = NULL; mTopView = false; mRenderViewCells = false; mTopDistance = 1.0f; mCutViewCells = false; mCutScene = false; mRenderErrors = false; mRenderBoxes = false; mRenderFilter = true; mRenderVisibilityEstimates = false; //mRenderVisibilityEstimates = true; mComputeGVS = false; mUseRandomColorPerPvsObject = false; //mUseRandomColorPerPvsObject = true; mHideByCost = false; mUseTransparency = false; mTransferFunction = 1.0f; mIndexBufferSize = 0; const int delay = 250; // in milliseconds mUpdateTimerId = startTimer(delay); mReplayTimerId = startTimer(1); // use fastest replay rate bool tmp; Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", tmp ); mUseFilter = tmp; Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter", tmp ); mUseSpatialFilter = tmp; mShowRenderCost = false; mShowPvsSizes = false; mShowComparison = false; mShowPiercingRays = false; mShowWeightedRays = false; mUseStandardColors = false; mShowWeightedCost = true; mShowDistanceWeightedPvs = true; mShowDistanceWeightedTriangles = false; mShowWeightedTriangles = false; mShowDistribution = 15; mSpatialFilterSize = 0.01; mPvsSize = 0; mRayVisualizationMethod = 0; mTrafoType = 0; mRenderError = 0.0f; mShowRays = false; mReplayMode = false; mPlacer = new ObjectPlacer(); mCurrentDynamicObjectIdx = -1; // export frame buffer during walkthrough mExportFrameBuffer = true; //mExportFrameBuffer = false; SetSceneCut(1000); mControlWidget = new QtRendererControlWidget(NULL); connect(mControlWidget, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int))); connect(mControlWidget, SIGNAL(SetTransferFunction(int)), this, SLOT(SetTransferFunction(int))); connect(mControlWidget, SIGNAL(UpdateAllPvs()), this, SLOT(UpdateAllPvs())); connect(mControlWidget, SIGNAL(ComputeVisibility()), this, SLOT(ComputeVisibility())); connect(mControlWidget, SIGNAL(StopComputation()), this, SLOT(StopComputation())); connect(mControlWidget, SIGNAL(SetRandomViewPoint()), this, SLOT(SetRandomViewPoint())); connect(mControlWidget, SIGNAL(StoreStatistics(void)), this, SLOT(StoreStatistics(void))); connect(mControlWidget, SIGNAL(ComputeGVS(void)), this, SLOT(ComputeGVS(void))); connect(mControlWidget, SIGNAL(ReplayViewPoints(void)), this, SLOT(ReplayViewPoints(void))); connect(mControlWidget, SIGNAL(NextObject(void)), this, SLOT(NextObject(void))); connect(mControlWidget, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int))); connect(mControlWidget, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int))); connect(mControlWidget, SIGNAL(SetTransparency(int)), this, SLOT(SetTransparency(int))); connect(mControlWidget, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int))); connect(mControlWidget, SIGNAL(SetSpatialFilterSize(int)), this, SLOT(SetSpatialFilterSize(int))); connect(mControlWidget, SIGNAL(SetHidingCost(int)), this, SLOT(SetHidingCost(int))); connect(mControlWidget, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool))); connect(mControlWidget, SIGNAL(SetShowRenderCost(bool)), this, SLOT(SetShowRenderCost(bool))); connect(mControlWidget, SIGNAL(SetUseTransparency(bool)), this, SLOT(SetUseTransparency(bool))); connect(mControlWidget, SIGNAL(SetShowPvsSizes(bool)), this, SLOT(SetShowPvsSizes(bool))); connect(mControlWidget, SIGNAL(SetShowComparison(bool)), this, SLOT(SetShowComparison(bool))); connect(mControlWidget, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool))); connect(mControlWidget, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool))); connect(mControlWidget, SIGNAL(SetHideByCost(bool)), this, SLOT(SetHideByCost(bool))); connect(mControlWidget, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool))); connect(mControlWidget, SIGNAL(SetRenderErrors(bool)), this, SLOT(SetRenderErrors(bool))); connect(mControlWidget, SIGNAL(SetRenderBoxes(bool)), this, SLOT(SetRenderBoxes(bool))); connect(mControlWidget, SIGNAL(SetRenderFilter(bool)), this, SLOT(SetRenderFilter(bool))); connect(mControlWidget, SIGNAL(SetRenderVisibilityEstimates(bool)), this, SLOT(SetRenderVisibilityEstimates(bool))); connect(mControlWidget, SIGNAL(SetUseFilter(bool)), this, SLOT(SetUseFilter(bool))); connect(mControlWidget, SIGNAL(SetUseSpatialFilter(bool)), this, SLOT(SetUseSpatialFilter(bool))); connect(mControlWidget, SIGNAL(SetShowPiercingRays(bool)), this, SLOT(SetShowPiercingRays(bool))); connect(mControlWidget, SIGNAL(SetShowWireFrame(bool)), this, SLOT(SetShowWireFrame(bool))); connect(mControlWidget, SIGNAL(SetShowWeightedRays(bool)), this, SLOT(SetShowWeightedRays(bool))); connect(mControlWidget, SIGNAL(SetShowWeightedCost(bool)), this, SLOT(SetShowWeightedCost(bool))); connect(mControlWidget, SIGNAL(SetShowDistanceWeightedTriangles(bool)), this, SLOT(SetShowDistanceWeightedTriangles(bool))); connect(mControlWidget, SIGNAL(SetShowDistanceWeightedPvs(bool)), this, SLOT(SetShowDistanceWeightedPvs(bool))); connect(mControlWidget, SIGNAL(SetShowWeightedTriangles(bool)), this, SLOT(SetShowWeightedTriangles(bool))); connect(mControlWidget, SIGNAL(UseConstColorForRayViz(bool)), this, SLOT(UseConstColorForRayViz(bool))); connect(mControlWidget, SIGNAL(UseRayLengthForRayViz(bool)), this, SLOT(UseRayLengthForRayViz(bool))); connect(mControlWidget, SIGNAL(SetShowContribution(bool)), this, SLOT(SetShowContribution(bool))); connect(mControlWidget, SIGNAL(SetShowDistribution(bool)), this, SLOT(SetShowDistribution(bool))); connect(mControlWidget, SIGNAL(SetShowDistribution1(bool)), this, SLOT(SetShowDistribution1(bool))); connect(mControlWidget, SIGNAL(SetShowDistribution2(bool)), this, SLOT(SetShowDistribution2(bool))); connect(mControlWidget, SIGNAL(SetShowDistribution3(bool)), this, SLOT(SetShowDistribution3(bool))); connect(mControlWidget, SIGNAL(SetShowDistribution4(bool)), this, SLOT(SetShowDistribution4(bool))); connect(mControlWidget, SIGNAL(SetShowRays(bool)), this, SLOT(SetShowRays(bool))); #if 1 connect(mControlWidget, SIGNAL(SetTranslation(bool)), this, SLOT(SetTranslation(bool))); connect(mControlWidget, SIGNAL(SetRotation(bool)), this, SLOT(SetRotation(bool))); connect(mControlWidget, SIGNAL(SetScale(bool)), this, SLOT(SetScale(bool))); #endif connect(mControlWidget, SIGNAL(UpdateDynamicObjects()), this, SLOT(UpdateDynamicObjects())); connect(mControlWidget, SIGNAL(DeleteDynamicObject()), this, SLOT(DeleteDynamicObject())); setWindowTitle("PVS Visualization"); // setting the main window size here //resize(800, 600); resize(640, 480); mControlWidget->show(); LoadObjects(); } void QtGlRendererWidget::UpdateAllPvs() { // $$ does not work so far:( mViewCellsManager->UpdatePvsForEvaluation(); // mViewCellsManager->FinalizeViewCells(false); } void QtGlRendererWidget::ComputeVisibility() { cerr<<"Compute Visibility called!\n"<isRunning()) mPreprocessorThread->RunThread(); } void QtGlRendererWidget::StopComputation() { cerr<<"stop computation called!\n"<GetPreprocessor()->mStopComputation = true; } void QtGlRendererWidget::SetRandomViewPoint() { cerr<<"setting random view point!\n"<GetViewPoint(mViewPoint); updateGL(); } void QtGlRendererWidget::StoreStatistics() { cerr<<"storing statistics!\n"<GetPreprocessor()->mCurrentSamples; cout<<"**********************************************" << endl; cout << "reached " << currentSamples << " samples " << " => writing file" << endl; LogWriter writer; writer.SetFilename("compare.log"); writer.Write(currentSamples, mViewCellsManager->GetViewCells()); cout << "finished writing file" << endl; mCompareInfo.clear(); updateGL(); } void QtGlRendererWidget::LoadObjects() { AxisAlignedBox3 sceneBox = mViewCellsManager->GetViewSpaceBox(); float x = 1.0f; float y = 20.0f; float z = 80.0f; AxisAlignedBox3 box(Vector3(0.5f * x, 0, -0.5f * z), Vector3(-0.5f * x, y, 0.5f * z)); // box.Scale(Vector3(0.02f, 0.1f, 0.1f)); box.Translate(-box.Min()); SceneGraphLeaf *leaf = GetPreprocessor()->GenerateBoxGeometry(box); mPlacer->AddObject(leaf); LoadObject("../data/teapot.bn"); LoadObject("../data/bunny.bn"); LoadObject("../data/horse.bn"); } void QtGlRendererWidget::NextObject() { mPlacer->NextObject(); } void QtGlRendererWidget::LoadObject(const string &filename) { cout << "Loading model " << filename << endl; SceneGraphLeaf *leaf = mViewCellsManager->GetPreprocessor()->LoadDynamicGeometry(filename); if (leaf) { mPlacer->AddObject(leaf); cout << "Loading finished" << endl; } else cerr << "Loading failed" << endl; //updateGL(); } QtGlRendererWidget::~QtGlRendererWidget() { delete mPlacer; } void QtGlRendererWidget::RenderRenderCost() { static vector costFunction; static float maxCost = -1; if (costFunction.size()==0) { ViewCellsTree *tree = mViewCellsManager->GetViewCellsTree(); if (tree) { tree->GetCostFunction(costFunction); maxCost = -1; for (int i=0; i < costFunction.size(); i++) { // cout<GetSize(); if (costFunction[i] > maxCost) maxCost = costFunction[i]; } } } int currentPos = (int)mViewCellsManager->GetViewCells().size(); float currentCost= -1; if (currentPos < costFunction.size()) currentCost = costFunction[currentPos]; #if 1 cout<<"costFunction.size()="<<(int)costFunction.size()<GetViewCells().size(); int filter = 0; if (mViewCellsManager) filter = mViewCellsManager->GetMaxFilterSize(); #if 0 //REMOVE_TEMPORARY s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f)", mFrame, mViewPoint.x, mViewPoint.y, mViewPoint.z, mViewDirection.x, mViewDirection.y, mViewDirection.z ); renderText(20, 20, s); s.sprintf("viewcells:%04d filter:%04d pvs:%04d error:%5.5f %", vc, filter, mPvsSize, mRenderError * 100.0f); renderText(20, 40, s); #endif glDisable(GL_LIGHTING); //qglColor(QColor(0, 255, 0)); glColor3f(0, 1, 0); QFont font40; font40.setPointSize(25); //s.sprintf("PVS: %04d", mPvsSize); //renderText(20, 40, s, font40); //s.sprintf("RAW TRI: %07d", mViewCellsManager->GetPreprocessor()->mGenericStats); //renderText(290, 40, s, font40); //s.sprintf("PVS TRI: %07d", mViewCellsManager->GetPreprocessor()->mGenericStats2); //renderText(290, 70, s, font40); s.sprintf("PVS TRI: %08d", (int)mCurrentPvsCost); //renderText(290, 70, s, font40); renderText(325, 40, s, font40); s.sprintf("error: %3.3f %", mRenderError * 100.0f); renderText(20, 40, s, font40); //renderText(290, 70, s, font40); glEnable(GL_LIGHTING); } void QtGlRendererWidget::SetViewCellGranularity(int number) { if (mViewCellsManager) { // mViewCellsManager->SetMaxFilterSize(number); // $$ tmp off mViewCellsManager->CollectViewCells(number); // $$ does not work so far:( // mViewCellsManager->UpdatePvsForEvaluation(); // mViewCellsManager->FinalizeViewCells(false); } updateGL(); } void QtGlRendererWidget::SetVisibilityFilterSize(int number) { if (mViewCellsManager) mViewCellsManager->SetMaxFilterSize(number); mPvsCache.Reset(); updateGL(); } void QtGlRendererWidget::SetSpatialFilterSize(int number) { mSpatialFilterSize = 1e-3*number; mPvsCache.Reset(); updateGL(); } void QtGlRendererWidget::SetSceneCut(int number) { // assume the cut plane can only be aligned with xz plane // shift it along y according to number, which is percentage of the bounding // box position if (mViewCellsManager) { const float f = number / 1000.0f; AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox(); Vector3 p = (1.0f - f) * box.Min() + f * box.Max(); mSceneCutPlane.mNormal = Vector3(0, -1, 0); mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p); updateGL(); } } void QtGlRendererWidget::SetHidingCost(int number) { mHidingCost = (float)number / 1000.0f; } void QtGlRendererWidget::SetTopDistance(int number) { mTopDistance = number / 1000.0f; updateGL(); } void QtGlRendererWidget::SetTransparency(int number) { mTransparency = number / 1000.0f; updateGL(); } float QtGlRendererWidget::ComputeRenderCost(ViewCell *vc) { float renderCost = 0; #ifdef USE_VERBOSE_PVS if (mShowDistanceWeightedPvs) { return vc->GetPvs().mStats.mDistanceWeightedPvs; } else if (mShowDistanceWeightedTriangles) { return vc->GetPvs().mStats.mDistanceWeightedTriangles; } else //if (mShowWeightedTriangles) { return vc->GetPvs().mStats.mWeightedTriangles; } #else return 0.0f; #endif } void QtGlRendererWidget::ComputeMaxValues(const ViewCellContainer &viewCells, int &maxPvs, int &maxPiercingRays, float &maxRelativeRays, float &maxRcCost) { maxPvs = -1; maxPiercingRays = 1; // not zero for savety maxRelativeRays = Limits::Small; // not zero for savety maxRcCost = Limits::Small; for (size_t i = 0; i < viewCells.size(); ++ i) { ViewCell *vc = viewCells[i]; if (mShowPvsSizes) // pvs size { //const int p = vc->GetPvs().CountObjectsInPvs(); const int p = vc->GetPvs().GetSize(); if (p > maxPvs) maxPvs = p; } else if (mShowPiercingRays) // relative number of rays { const int piercingRays = vc->GetNumPiercingRays(); if (piercingRays > maxPiercingRays) maxPiercingRays = piercingRays; } else if (mShowWeightedRays) { const int piercingRays = vc->GetNumPiercingRays(); const float relativeArea = vc->GetBox().SurfaceArea() / mViewCellsManager->GetViewSpaceBox().SurfaceArea(); if ((float)piercingRays / relativeArea > maxRelativeRays) maxRelativeRays = (float)piercingRays / relativeArea; } else if (mShowWeightedCost) { const float rcCost = ComputeRenderCost(vc); mViewCellsManager->UpdateScalarPvsCost(vc, rcCost); if (rcCost > maxRcCost) maxRcCost = rcCost; } } } void QtGlRendererWidget::RenderViewCells() { mUseFalseColors = true; //glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); //glDisable(GL_CULL_FACE); if (mCutViewCells) { double eq[4]; eq[0] = mSceneCutPlane.mNormal.x; eq[1] = mSceneCutPlane.mNormal.y; eq[2] = mSceneCutPlane.mNormal.z; eq[3] = mSceneCutPlane.mD; glClipPlane(GL_CLIP_PLANE0, eq); glEnable(GL_CLIP_PLANE0); } ViewCellContainer &viewcells = mViewCellsManager->GetViewCells(); int maxPvs, maxPiercingRays; float maxRelativeRays, maxRcCost; ComputeMaxValues(viewcells, maxPvs, maxPiercingRays, maxRelativeRays, maxRcCost); // matt: temp hack //maxRcCost = 5000.0f; //cout << "maxRcCost: " << maxRcCost << endl; int i; // transparency if (!mUseTransparency) { glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); } else { glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glBlendFunc(GL_SRC_ALPHA, GL_ONE); for (i = 0; i < viewcells.size(); ++ i) { ViewCell *vc = viewcells[i]; const float dist = SqrDistance(mDummyViewPoint, vc->GetBox().Center()); vc->SetDistance(dist); } sort(viewcells.begin(), viewcells.end(), nearerThan); } //mWireFrame = true; // normal rendering //if (!mShowPvsSizes && !mShowPiercingRays && !mShowWeightedRays && !mShowWeightedCost && !mShowComparison) if (mUseStandardColors) { for (i = 0; i < viewcells.size(); ++ i) { ViewCell *vc = viewcells[i]; RgbColor c; //if (!mShowPvsSizes && !mShowPiercingRays) c = vc->GetColor(); glColor3f(c.r, c.g, c.b); if (!mHideByCost || (mHidingCost < (vc->GetNumPiercingRays() / (float)maxPiercingRays))) { RenderViewCell(vc); } } } else // using specialised colors { if (!mShowComparison) AssignImportanceByRelativeValue(viewcells, maxPvs, maxPiercingRays, maxRelativeRays, maxRcCost); else { if (mCompareInfo.empty()) { LogReader reader; reader.SetFilename("compare.log"); int samples; reader.Read(samples, mCompareInfo); } AssignColorByComparison(viewcells, mCompareInfo); } glEnable(GL_DEPTH_TEST); } glEnable(GL_CULL_FACE); glDisable(GL_CULL_FACE); glDisable(GL_CLIP_PLANE0); mUseFalseColors = false; mWireFrame = false; glPopAttrib(); } void QtGlRendererWidget::AssignImportanceByRelativeValue(const ViewCellContainer &viewCells, int &maxPvs, int &maxPiercingRays, float &maxRelativeRays, float &maxRcCost) { for (size_t i = 0; i < viewCells.size(); ++ i) { RgbColor c; ViewCell *vc = viewCells[i]; float importance; if (mShowPiercingRays) { importance = mTransferFunction * ((float)vc->GetNumPiercingRays() / (float)maxPiercingRays); } else if (mShowWeightedRays) // relative number of rays { float relativeArea = vc->GetBox().SurfaceArea() / mViewCellsManager->GetViewSpaceBox().SurfaceArea(); if (relativeArea < Limits::Small) relativeArea = Limits::Small; importance = mTransferFunction * ((float)vc->GetNumPiercingRays() / relativeArea) / maxRelativeRays; } else if (mShowPvsSizes) // pvs size { importance = mTransferFunction * ((float)vc->GetPvs().GetSize() / (float)maxPvs); } // weighted render cost else if (mShowWeightedCost) { const float rcCost = mTransferFunction * ComputeRenderCost(vc); importance = rcCost / maxRcCost; } if (importance > 1.0f) importance = 1.0f; // c = RgbColor(importance, 1.0f - importance, 0.0f); c = RainbowColorMapping(importance); glColor4f(c.r, c.g, c.b, 1.0f - mTransparency); if (!mHideByCost || (mHidingCost < importance)) { RenderViewCell(vc); } } } void QtGlRendererWidget::AssignColorByComparison(const ViewCellContainer &viewcells, //const ViewCellInfoContainer &infos1, const ViewCellInfoContainer &compareInfo) { if (viewcells.size() > compareInfo.size()) { cerr << "loaded size (" << (int)compareInfo.size() << ") does not fit to view cells size (" << (int)viewcells.size() << ")" << endl; return; } //const float maxRatio = 1.0f; const float maxRatio = 2.0f; const float minRatio = 0.0f; const float scale = 1.0f / (maxRatio - minRatio); for (size_t i = 0; i < viewcells.size(); ++ i) { RgbColor c; ViewCell *vc = viewcells[i]; //ViewCellInfo vc1Info = infos1[i]; ViewCellInfo vc2Info = compareInfo[i]; //const float vcRatio = vc->GetNumPiercingRays() / vc2Info.mPiercingRays + Limits::Small; float vcRatio = 1.0f;//maxRatio; if (vc2Info.mPvsSize > Limits::Small) vcRatio = (float)vc->GetPvs().GetSize() / vc2Info.mPvsSize; // truncate here if (vcRatio > maxRatio) vcRatio = 1.0f; const float importance = (vcRatio - minRatio) * scale; if (0 && (i < 20)) { cout << "pvs1: " << vc->GetPvs().GetSize() << " pvs2: " << compareInfo[i].mPvsSize << " importance: " << importance << endl; } // c = RgbColor(importance, 1.0f - importance, 0.0f); c = RainbowColorMapping(importance); glColor4f(c.r, c.g, c.b, 1.0f); if (1)//!mHideByCost || (mHidingCost < importance)) { RenderViewCell(vc); } } } /**********************************************************************/ /* QtRendererControlWidget implementation */ /**********************************************************************/ QGroupBox *QtRendererControlWidget::CreateVisualizationPanel(QWidget *parent) { QRadioButton *rb1, *rb2, *rb3, *rb4, *rb5; rb1 = new QRadioButton("random colors", parent); rb1->setText("random"); connect(rb1, SIGNAL(toggled(bool)), SIGNAL(SetShowWireFrame(bool))); // Create a check box to be in the group box rb2 = new QRadioButton("piercing rays", parent); rb2->setText("piercing rays"); //vl->addWidget(rb1); connect(rb2, SIGNAL(toggled(bool)), SIGNAL(SetShowPiercingRays(bool))); rb3 = new QRadioButton("pvs size", parent); rb3->setText("pvs size"); connect(rb3, SIGNAL(toggled(bool)), SIGNAL(SetShowPvsSizes(bool))); rb4 = new QRadioButton("weighted rays", parent); rb4->setText("weighted rays"); connect(rb4, SIGNAL(toggled(bool)), SIGNAL(SetShowWeightedRays(bool))); rb5 = new QRadioButton("pvs cost", parent); rb5->setText("pvs cost"); connect(rb5, SIGNAL(toggled(bool)), SIGNAL(SetShowWeightedCost(bool))); QGroupBox *groupBox = new QGroupBox("PVS Visualization"); QVBoxLayout *vbox2 = new QVBoxLayout; vbox2->addWidget(rb1); vbox2->addWidget(rb2); vbox2->addWidget(rb3); vbox2->addWidget(rb4); vbox2->addWidget(rb5); rb5->setChecked(true); vbox2->addStretch(1); groupBox->setLayout(vbox2); return groupBox; } QGroupBox *QtRendererControlWidget::CreateTrafoPanel(QWidget *parent) { QRadioButton *rb1, *rb2, *rb3; rb1 = new QRadioButton("translation", parent); rb1->setText("translation"); connect(rb1, SIGNAL(toggled(bool)), SIGNAL(SetTranslation(bool))); // Create a check box to be in the group box rb2 = new QRadioButton("scale", parent); rb2->setText("scale"); //vl->addWidget(rb1); connect(rb2, SIGNAL(toggled(bool)), SIGNAL(SetScale(bool))); rb3 = new QRadioButton("rotation", parent); rb3->setText("rotation"); connect(rb3, SIGNAL(toggled(bool)), SIGNAL(SetRotation(bool))); QVBoxLayout *vbox2 = new QVBoxLayout; QGroupBox *groupBox = new QGroupBox("Dynamic Obojects"); vbox2->addWidget(rb1); vbox2->addWidget(rb2); vbox2->addWidget(rb3); rb1->setChecked(true); vbox2->addStretch(1); QPushButton *button = new QPushButton("Update", groupBox); vbox2->addWidget(button); connect(button, SIGNAL(clicked()), SIGNAL(UpdateDynamicObjects())); button = new QPushButton("Delete", groupBox); vbox2->addWidget(button); connect(button, SIGNAL(clicked()), SIGNAL(DeleteDynamicObject())); button = new QPushButton("Next object", groupBox); vbox2->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SIGNAL(NextObject())); groupBox->setLayout(vbox2); return groupBox; } QGroupBox *QtRendererControlWidget::CreateRenderCostPanel(QWidget *parent) { QRadioButton *rb1, *rb2, *rb3; // Create a check box to be in the group box rb1 = new QRadioButton("triangles", parent); rb1->setText("triangles"); connect(rb1, SIGNAL(toggled(bool)), SIGNAL(SetShowWeightedTriangles(bool))); rb2 = new QRadioButton("distance weighted pvs", parent); rb2->setText("distance weighted"); connect(rb2, SIGNAL(toggled(bool)), SIGNAL(SetShowDistanceWeightedPvs(bool))); rb3 = new QRadioButton("distance weighted triangles", parent); rb3->setText("distance weighted triangles"); connect(rb3, SIGNAL(toggled(bool)), SIGNAL(SetShowDistanceWeightedTriangles(bool))); QGroupBox *groupBox = new QGroupBox("Render cost options"); QVBoxLayout *vbox2 = new QVBoxLayout; vbox2->addWidget(rb1); vbox2->addWidget(rb2); vbox2->addWidget(rb3); rb1->setChecked(true); vbox2->addStretch(1); groupBox->setLayout(vbox2); return groupBox; } QGroupBox *QtRendererControlWidget::CreateRayVisualizationPanel(QWidget *parent) { QRadioButton *rb1, *rb2, *rb3, *rb4; // Create a check box to be in the group box rb1 = new QRadioButton("const color", parent); rb1->setText("const color"); //vl->addWidget(rb1); connect(rb1, SIGNAL(toggled(bool)), SIGNAL(UseConstColorForRayViz(bool))); rb2 = new QRadioButton("ray length", parent); rb2->setText("ray length"); connect(rb2, SIGNAL(toggled(bool)), SIGNAL(UseRayLengthForRayViz(bool))); rb3 = new QRadioButton("contribution", parent); rb3->setText("contribution"); connect(rb3, SIGNAL(toggled(bool)), SIGNAL(SetShowContribution(bool))); rb4 = new QRadioButton("distribution", parent); rb4->setText("distribution"); connect(rb4, SIGNAL(toggled(bool)), SIGNAL(SetShowDistribution(bool))); /////////////////////////// QGroupBox *groupBox = new QGroupBox("Ray visualization"); QVBoxLayout *vbox2 = new QVBoxLayout; vbox2->addWidget(rb1); vbox2->addWidget(rb2); vbox2->addWidget(rb3); vbox2->addWidget(rb4); rb1->setChecked(true); QCheckBox *cb = new QCheckBox("Distribution 1", parent); vbox2->addWidget(cb); cb->setChecked(true); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowDistribution1(bool))); cb = new QCheckBox("Distribution 2", parent); vbox2->addWidget(cb); cb->setChecked(true); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowDistribution2(bool))); cb = new QCheckBox("Distribution 3", parent); vbox2->addWidget(cb); cb->setChecked(true); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowDistribution3(bool))); cb = new QCheckBox("Distribution 4", parent); vbox2->addWidget(cb); cb->setChecked(true); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowDistribution4(bool))); vbox2->addStretch(1); groupBox->setLayout(vbox2); return groupBox; } QtRendererControlWidget::QtRendererControlWidget(QWidget * parent, Qt::WFlags f): QWidget(parent, f) { QVBoxLayout *vl = new QVBoxLayout; setLayout(vl); //QWidget *vbox; //vbox = new QGroupBox("Render Controls", this); //layout()->addWidget(vbox); //vl = new QVBoxLayout; //vbox->setLayout(vl); QLabel *label; QSlider *slider; QPushButton *button; #if 0//REMOVE_TEMPORARY label = new QLabel("Granularity"); //vbox->layout()->addWidget(label); vl->addWidget(label); slider = new QSlider(Qt::Horizontal); vl->addWidget(slider); slider->show(); slider->setRange(1, 10000); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(200); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int))); /////////////////////////// label = new QLabel("Transfer function"); vl->addWidget(label); slider = new QSlider(Qt::Horizontal); vl->addWidget(slider); slider->show(); slider->setRange(1, 10000); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(100); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTransferFunction(int))); ////////////////////////////////////////7 button = new QPushButton("Update all PVSs"); vl->addWidget(button); connect(button, SIGNAL(clicked()), SLOT(UpdateAllPvs())); ////////////////////////////////////////77777 label = new QLabel("Filter size"); vl->addWidget(label); slider = new QSlider(Qt::Horizontal); vl->addWidget(slider); slider->show(); slider->setRange(1, 100); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(3); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int))); #endif /////////////////////////////////// QWidget *hbox = new QWidget(); vl->addWidget(hbox); QHBoxLayout *hlayout = new QHBoxLayout; hbox->setLayout(hlayout); QCheckBox *cb = new QCheckBox("Show viewcells", hbox); hlayout->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool))); cb = new QCheckBox("Render errors", hbox); hlayout->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool))); #if REMOVE_TEMPORARY cb = new QCheckBox("Render cost curve", hbox); hlayout->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRenderCost(bool))); #endif cb = new QCheckBox("Show rays", hbox); hlayout->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRays(bool))); #if REMOVE_TEMPORARY cb = new QCheckBox("Show Comparison", hbox); hlayout->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowComparison(bool))); #endif ////////////////// QHBoxLayout *vh = new QHBoxLayout; QGroupBox *myBox = new QGroupBox("Visualization"); myBox->setLayout(vh); vl->addWidget(myBox, 0, 0); QGroupBox *groupBox = CreateVisualizationPanel(hbox); vh->addWidget(groupBox, 0, 0); #if REMOVE_TEMPORARY QGroupBox *groupBox2 = CreateRenderCostPanel(hbox); vh->addWidget(groupBox2, 0, 0); QGroupBox *groupBox3 = CreateRayVisualizationPanel(hbox); vh->addWidget(groupBox3, 0, 0); #endif #if 1 QGroupBox *groupBox4 = CreateTrafoPanel(hbox); vh->addWidget(groupBox4, 0, 0); #endif ////////////////////////////////// bool tmp = false; const int range = 1000; //vbox->resize(800,150); QWidget *vbox; vbox = new QGroupBox("Rendering", this); layout()->addWidget(vbox); vl = new QVBoxLayout; vbox->setLayout(vl); cb = new QCheckBox("Cut view cells", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool))); slider = new QSlider(Qt::Horizontal, vbox); vbox->layout()->addWidget(slider); slider->show(); slider->setRange(0, 1000); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(1000); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int))); cb = new QCheckBox("Use spatial filter", vbox); vbox->layout()->addWidget(cb); Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter", tmp); cb->setChecked(tmp); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseSpatialFilter(bool))); label = new QLabel("Spatial Filter size"); vbox->layout()->addWidget(label); slider = new QSlider(Qt::Horizontal, vbox); vbox->layout()->addWidget(slider); slider->show(); slider->setRange(1, 100); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(10); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSpatialFilterSize(int))); //////////////////////////// cb = new QCheckBox("Hide view cells by render cost ", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetHideByCost(bool))); label = new QLabel("Hide by cost"); vbox->layout()->addWidget(label); // the render cost visualization slider = new QSlider(Qt::Horizontal, vbox); vbox->layout()->addWidget(slider); slider->show(); slider->setRange(0, range); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(0); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetHidingCost(int))); /////////////////////////////////////////// cb = new QCheckBox("Top View", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool))); label = new QLabel("Top distance"); vbox->layout()->addWidget(label); slider = new QSlider(Qt::Horizontal, vbox); vbox->layout()->addWidget(slider); slider->show(); slider->setRange(1, 1000); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(500); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int))); /////////////////////////////////////////// #if REMOVE_TEMPORARY cb = new QCheckBox("Transparency", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseTransparency(bool))); label = new QLabel("Use transparency"); vbox->layout()->addWidget(label); // the render cost visualization slider = new QSlider(Qt::Horizontal, vbox); vbox->layout()->addWidget(slider); slider->show(); slider->setRange(0, range); slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); slider->setValue(0); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTransparency(int))); #endif ////////////////////////////// #if REMOVE_TEMPORARY cb = new QCheckBox("Cut scene", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool))); cb = new QCheckBox("Render boxes", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderBoxes(bool))); cb = new QCheckBox("Render visibility estimates", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderVisibilityEstimates(bool))); #endif #if REMOVE_TEMPORARY cb = new QCheckBox("Use filter", vbox); vbox->layout()->addWidget(cb); Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", tmp); cb->setChecked(tmp); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseFilter(bool))); #endif #if REMOVE_TEMPORARY cb = new QCheckBox("Render filter", vbox); vbox->layout()->addWidget(cb); cb->setChecked(true); connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderFilter(bool))); /*vbox = new QGroupBox("PVS Errors", this); layout()->addWidget(vbox); vl = new QVBoxLayout; vbox->setLayout(vl); button = new QPushButton("Compute Visibility", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SLOT(ComputeVisibility())); button = new QPushButton("Stop Computation", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SLOT(StopComputation())); button = new QPushButton("Set Random View Point", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SLOT(SetRandomViewPoint()));*/ button = new QPushButton("Store statistics", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SIGNAL(StoreStatistics())); #endif #if 0 button = new QPushButton("Compute GVS", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SIGNAL(ComputeGVS())); #endif button = new QPushButton("Replay view points", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked()), SIGNAL(ReplayViewPoints())); /*cb = new QCheckBox("Stats", vbox); vbox->layout()->addWidget(cb); cb->setChecked(false); connect(cb, SIGNAL(toggled(bool)), SIGNAL(StoreStatistics()));*/ if (0) { vbox = new QGroupBox("PVS Errors", this); layout()->addWidget(vbox); vl = new QVBoxLayout; vbox->setLayout(vl); mPvsErrorWidget = new QListWidget(vbox); vbox->layout()->addWidget(mPvsErrorWidget); connect(mPvsErrorWidget, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(PvsErrorClicked(const QModelIndex &))); button = new QPushButton("Next Error Frame", vbox); vbox->layout()->addWidget(button); connect(button, SIGNAL(clicked(void)), SLOT(FocusNextPvsErrorFrame(void))); } //connect(button, SIGNAL(clicked(void)), SLOT(StoreStatistics(void))); ////////////////////////////////////////// setWindowTitle("Preprocessor Control Widget"); adjustSize(); } void QtRendererControlWidget::FocusNextPvsErrorFrame(void) {} void QtRendererControlWidget::UpdatePvsErrorItem(int row, GlRendererBuffer::PvsErrorEntry &pvsErrorEntry) { QListWidgetItem *i = mPvsErrorWidget->item(row); QString s; s.sprintf("%5.5f", pvsErrorEntry.mError); if (i) { i->setText(s); } else { new QListWidgetItem(s, mPvsErrorWidget); } mPvsErrorWidget->update(); } /*********************************************************************/ /* QtGlDebuggerWidget implementation */ /*********************************************************************/ QtGlDebuggerWidget::QtGlDebuggerWidget(QtGlRendererBuffer *buf, QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf) { // create the pbuffer //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this); //mUpdateTimerId = startTimer(20); setWindowTitle(("OpenGL pbuffers")); } QtGlDebuggerWidget::~QtGlDebuggerWidget() { mRenderBuffer->releaseFromDynamicTexture(); glDeleteTextures(1, &dynamicTexture); DEL_PTR(mRenderBuffer); } void QtGlDebuggerWidget::initializeGL() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 10, 100); glTranslatef(-0.5f, -0.5f, -0.5f); glTranslatef(0.0f, 0.0f, -15.0f); glMatrixMode(GL_MODELVIEW); glEnable(GL_CULL_FACE); initCommon(); initPbuffer(); } void QtGlDebuggerWidget::resizeGL(int w, int h) { glViewport(0, 0, w, h); } void QtGlDebuggerWidget::paintGL() { // draw a spinning cube into the pbuffer.. mRenderBuffer->makeCurrent(); BeamSampleStatistics stats; mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats); glFlush(); // rendering directly to a texture is not supported on X11, unfortunately mRenderBuffer->updateDynamicTexture(dynamicTexture); // and use the pbuffer contents as a texture when rendering the // background and the bouncing cubes makeCurrent(); glBindTexture(GL_TEXTURE_2D, dynamicTexture); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw the background glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } void QtGlDebuggerWidget::initPbuffer() { // set up the pbuffer context mRenderBuffer->makeCurrent(); // generate a texture that has the same size/format as the pbuffer dynamicTexture = mRenderBuffer->generateDynamicTexture(); // bind the dynamic texture to the pbuffer - this is a no-op under X11 mRenderBuffer->bindToDynamicTexture(dynamicTexture); //makeCurrent(); } void QtGlDebuggerWidget::initCommon() { glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); } void QtGlRendererWidget::_RenderColoredPvs() { // note: could be done more efficiently using color buffers mPvsSize = mPvsCache.mPvs.GetSize(); ObjectPvsIterator it = mPvsCache.mPvs.GetIterator(); PvsData pvsData; while (it.HasMoreEntries()) { Intersectable *obj = it.Next(pvsData); RgbColor color; //cerr << "sumpdf: " << pvsData.mSumPdf << endl; if (mUseRandomColorPerPvsObject) { if (obj->Type() == Intersectable::KD_INTERSECTABLE) { KdIntersectable *kdint = static_cast(obj); if (kdint->mGenericIdx == -1) { kdint->mGenericIdx = (int)mColors.size(); mColors.push_back(RandomColor(0, 1)); } color = mColors[kdint->mGenericIdx]; } } else { color = RainbowColorMapping(mTransferFunction * log10(pvsData.mSumPdf + 1)); } glColor3f(color.r, color.g, color.b); mUseForcedColors = true; RenderIntersectable(obj); mUseForcedColors = false; } } void QtGlRendererWidget::UpdateDynamicObjects() { preprocessor->ScheduleUpdateDynamicObjects(); } void QtGlRendererWidget::ReplayViewPoints() { ViewCellPointsList *vcPoints = mViewCellsManager->GetViewCellPointsList(); ViewCellPointsList::const_iterator vit, vit_end = vcPoints->end(); sViewPointsList.clear(); for (vit = vcPoints->begin(); vit != vit_end; ++ vit) { ViewCellPoints *vp = *vit; SimpleRayContainer::const_iterator rit, rit_end = vp->second.end(); for (rit = vp->second.begin(); rit != rit_end; ++ rit) { sViewPointsList.push_back(*rit); } } if (!sViewPointsList.empty()) { cout << "replaying " << (int)sViewPointsList.size() << " view points " << endl; mReplayMode = true; if (mExportFrameBuffer) GetPreprocessor()->mSynchronize = true; sCurrentSamples = GetPreprocessor()->mCurrentSamples; sViewPointsListIt = sViewPointsList.begin(); } } Vector3 QtGlRendererWidget::Unproject(int x, int y) { // swap y coordinate y = GetHeight() - y; // HACK: should come from camera! double projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, projection); double modelview[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelview); const int viewport[4] = {0,0, GetWidth(), GetHeight()}; RenderScene(); float z; glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z); GLdouble rx, ry, rz; gluUnProject(x, y, z, modelview, projection, viewport, &rx, &ry, &rz); return Vector3(rx, ry, rz); } int QtGlRendererWidget::FindDynamicObject(float x, float y) { if (GetPreprocessor()->mDynamicObjects.empty()) return -1; makeCurrent(); // this is the same as in every OpenGL picking example const int maxSize = 512; // see below for an explanation on the buffer content GLuint buffer[maxSize]; glSelectBuffer(maxSize, buffer); // enter select mode glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glViewport(0, 0, width(), height()); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); const float w = 1.0f; //gluPickMatrix(x, y, 1000.0, 1000.0, viewport); gluPickMatrix((GLdouble)x, (GLdouble)(viewport[3] - y), w, w, viewport); GLfloat aspect = (GLfloat) width() / height(); gluPerspective(70.0f, aspect, 0.1f, 2.0f * Magnitude(mSceneGraph->GetBox().Diagonal())); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetupCamera(); for (GLuint i = 0; i < GetPreprocessor()->mDynamicObjects.size(); ++ i) { glLoadName(i); _RenderDynamicObject(GetPreprocessor()->mDynamicObjects[i]); } glFlush(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); int hits = glRenderMode(GL_RENDER); // finally release the rendering context again if (!hits) { cout << "no object picked" << endl; return -1; } //processHits(hits, buffer); // Each hit takes 4 items in the buffer. // The first item is the number of names on the name stack when the hit occured. // The second item is the minimum z value of all the verticies that intersected // the viewing area at the time of the hit. The third item is the maximum z value // of all the vertices that intersected the viewing area at the time of the hit // and the last item is the content of the name stack at the time of the hit // (name of the object). We are only interested in the object name // (number of the surface). // return the name of the clicked surface return buffer[3]; } void QtGlRendererWidget::DeleteDynamicObject() { Preprocessor *p = GetPreprocessor(); if ((mCurrentDynamicObjectIdx < 0) || (mCurrentDynamicObjectIdx >= p->mDynamicObjects.size())) return; cout << "deleting object" << endl; SceneGraphLeaf *l = p->mDynamicObjects[mCurrentDynamicObjectIdx]; // tell the preprocessor that an object was deleted p->ObjectRemoved(l); swap(p->mDynamicObjects[mCurrentDynamicObjectIdx], p->mDynamicObjects.back()); p->mDynamicObjects.pop_back(); delete l; mCurrentDynamicObjectIdx = -1; } }