#include "Mesh.h" #include "glInterface.h" #include "OcclusionQuery.h" #include "GlRenderer.h" #include "ViewCellsManager.h" #include "SceneGraph.h" #include "Pvs.h" #include "Viewcell.h" #include "Beam.h" #include "KdTree.h" #include "Environment.h" #include "Triangle3.h" #include "IntersectableWrapper.h" #include "BvHierarchy.h" //#include //#include namespace GtpVisibilityPreprocessor { static bool arbQuerySupport = false; static bool nvQuerySupport = false; static void InitExtensions() { GLenum err = glewInit(); if (GLEW_OK != err) { // problem: glewInit failed, something is seriously wrong cerr << "Error: " << glewGetErrorString(err) << endl; exit(1); } if (GLEW_ARB_occlusion_query) arbQuerySupport = true; if (GLEW_NV_occlusion_query) nvQuerySupport = true; if (!arbQuerySupport && !nvQuerySupport) { cout << "I require the GL_ARB_occlusion_query or the GL_NV_occlusion_query OpenGL extension to work.\n"; exit(1); } } GlRenderer::GlRenderer(SceneGraph *sceneGraph, ViewCellsManager *viewCellsManager, KdTree *tree): Renderer(sceneGraph, viewCellsManager), mKdTree(tree) { mSceneGraph->CollectObjects(&mObjects); // mViewCellsManager->GetViewPoint(mViewPoint); mViewPoint = mSceneGraph->GetBox().Center(); mViewDirection = Vector3(0,0,1); // mViewPoint = Vector3(991.7, 187.8, -271); // mViewDirection = Vector3(0.9, 0, -0.4); // timerId = startTimer(10); // debug coords for atlanta // mViewPoint = Vector3(3473, 6.778, -1699); // mViewDirection = Vector3(-0.2432, 0, 0.97); mFrame = 0; mWireFrame = false; Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace); mSnapErrorFrames = true; mSnapPrefix = "snap/"; mUseForcedColors = false; mUseGlLists = true; //mUseGlLists = false; } GlRenderer::~GlRenderer() { cerr<<"gl renderer destructor..\n"; //CLEAR_CONTAINER(sQueries); CLEAR_CONTAINER(mOcclusionQueries); cerr<<"done."<GetItem(); glBegin(GL_TRIANGLES); glVertex3f(t.mVertices[0].x, t.mVertices[0].y, t.mVertices[0].z); glVertex3f(t.mVertices[1].x, t.mVertices[1].y, t.mVertices[1].z); glVertex3f(t.mVertices[2].x, t.mVertices[2].y, t.mVertices[2].z); glEnd(); } void GlRenderer::RenderIntersectable(Intersectable *object) { glPushAttrib(GL_CURRENT_BIT); if (mUseFalseColors) SetupFalseColor(object->mId); switch (object->Type()) { case Intersectable::MESH_INSTANCE: RenderMeshInstance((MeshInstance *)object); break; case Intersectable::VIEW_CELL: RenderViewCell(dynamic_cast(object)); break; case Intersectable::TRANSFORMED_MESH_INSTANCE: RenderTransformedMeshInstance(dynamic_cast(object)); break; case Intersectable::TRIANGLE_INTERSECTABLE: RenderTriangle(dynamic_cast(object)); break; case Intersectable::BVH_INTERSECTABLE: { BvhNode *node = (dynamic_cast(object))->GetItem(); // RenderBvhNode(node); RenderBox(node->GetBoundingBox()); break; } default: cerr<<"Rendering this object not yet implemented\n"; break; } glPopAttrib(); } void GlRenderer::RenderRays(const VssRayContainer &rays) { VssRayContainer::const_iterator it = rays.begin(), it_end = rays.end(); glBegin(GL_LINES); for (; it != it_end; ++it) { VssRay *ray = *it; float importance = log10(1e3*ray->mWeightedPvsContribution)/3.0f; // cout<<"w="<mWeightedPvsContribution<<" r="<mWeightedPvsContribution; glColor3f(importance, importance, importance); glVertex3fv(&ray->mOrigin.x); glVertex3fv(&ray->mTermination.x); } glEnd(); } void GlRenderer::RenderViewCell(ViewCell *vc) { if (vc->GetMesh()) { if (!mUseFalseColors) { if (vc->GetValid()) glColor3f(0,1,0); else glColor3f(0,0,1); } RenderMesh(vc->GetMesh()); } else { // render viewcells in the subtree if (!vc->IsLeaf()) { ViewCellInterior *vci = (ViewCellInterior *) vc; ViewCellContainer::iterator it = vci->mChildren.begin(); for (; it != vci->mChildren.end(); ++it) { RenderViewCell(*it); } } else { // cerr<<"Empty viewcell mesh\n"; } } } void GlRenderer::RenderMeshInstance(MeshInstance *mi) { RenderMesh(mi->GetMesh()); } void GlRenderer::RenderTransformedMeshInstance(TransformedMeshInstance *mi) { // apply world transform before rendering Matrix4x4 m; mi->GetWorldTransform(m); glPushMatrix(); /* cout << "\n"; for (int i = 0; i < 4; ++ i) for (int j = 0; j < 4; ++ j) cout << m.x[i][j] << " "; cout << "\n"*/ glMultMatrixf((float *)m.x); /*GLfloat dummy[16]; glGetFloatv(GL_MODELVIEW_MATRIX, dummy); for (int i = 0; i < 16; ++ i) cout << dummy[i] << " "; cout << endl;*/ RenderMesh(mi->GetMesh()); glPopMatrix(); } void GlRenderer::SetupFalseColor(const int id) { // swap bits of the color glColor3ub(id&255, (id>>8)&255, (id>>16)&255); } int GlRenderer::GetId(int r, int g, int b) const { return r + (g << 8) + (b << 16); } void GlRenderer::SetupMaterial(Material *m) { if (m) glColor3fv(&(m->mDiffuseColor.r)); } void GlRenderer::RenderMesh(Mesh *mesh) { int i = 0; if (!mUseFalseColors && !mUseForcedColors) SetupMaterial(mesh->mMaterial); for (i=0; i < mesh->mFaces.size(); i++) { if (mWireFrame) glBegin(GL_LINE_LOOP); else glBegin(GL_POLYGON); Face *face = mesh->mFaces[i]; for (int j = 0; j < face->mVertexIndices.size(); j++) { glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x); } glEnd(); } } void GlRenderer::InitGL() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_CULL_FACE); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); InitExtensions(); #if 0 GLfloat mat_ambient[] = { 0.5, 0.5, 0.5, 1.0 }; /* mat_specular and mat_shininess are NOT default values */ GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_specular[] = { 0.3, 0.3, 0.3, 1.0 }; GLfloat mat_shininess[] = { 1.0 }; GLfloat light_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; GLfloat light_diffuse[] = { 0.4, 0.4, 0.4, 1.0 }; GLfloat light_specular[] = { 0.3, 0.3, 0.3, 1.0 }; GLfloat lmodel_ambient[] = { 0.3, 0.3, 0.3, 1.0 }; // default Material 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); // a light glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); // set position of the light GLfloat infinite_light[] = { 1.0, 0.8, 1.0, 0.0 }; glLightfv (GL_LIGHT0, GL_POSITION, infinite_light); // set position of the light2 GLfloat infinite_light2[] = { -0.3, 1.5, 1.0, 0.0 }; glLightfv (GL_LIGHT1, GL_POSITION, infinite_light2); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); // glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR); glEnable(GL_COLOR_MATERIAL); glShadeModel( GL_FLAT ); glDepthFunc( GL_LESS ); glEnable( GL_DEPTH_TEST ); #endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable( GL_NORMALIZE ); glClearColor(0.0f, 0.0f, 1.0f, 1.0f); } void GlRenderer::SetupProjection(const int w, const int h, const float angle) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(angle, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal())); glMatrixMode(GL_MODELVIEW); } void GlRenderer::SetupCamera() { Vector3 target = mViewPoint + mViewDirection; Vector3 up(0,1,0); if (abs(DotProd(mViewDirection, up)) > 0.99f) up = Vector3(1, 0, 0); glLoadIdentity(); gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z, target.x, target.y, target.z, up.x, up.y, up.z); } void GlRenderer::_RenderScene() { ObjectContainer::const_iterator oi = mObjects.begin(); for (; oi != mObjects.end(); oi++) RenderIntersectable(*oi); } bool GlRenderer::RenderScene() { static int glList = -1; if (mUseGlLists) { if (glList == -1) { glList = glGenLists(1); glNewList(glList, GL_COMPILE); _RenderScene(); glEndList(); } glCallList(glList); } else _RenderScene(); return true; } void GlRendererBuffer::EvalQueryWithItemBuffer( //RenderCostSample &sample ) { // read back the texture glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPixelBuffer); unsigned int *p = mPixelBuffer; for (int y = 0; y < GetHeight(); y++) { for (int x = 0; x < GetWidth(); x++, p++) { unsigned int id = (*p) & 0xFFFFFF; if (id != 0xFFFFFF) ++ mObjects[id]->mCounter; } } } /****************************************************************/ /* GlRendererBuffer implementation */ /****************************************************************/ GlRendererBuffer::GlRendererBuffer(SceneGraph *sceneGraph, ViewCellsManager *viewcells, KdTree *tree): GlRenderer(sceneGraph, viewcells, tree) { mPixelBuffer = NULL; // implement width and height in subclasses } void GlRendererBuffer::EvalQueryWithOcclusionQueries( //RenderCostSample &sample ) { glDepthFunc(GL_LEQUAL); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); // simulate detectemptyviewspace using backface culling if (mDetectEmptyViewSpace) { glEnable(GL_CULL_FACE); //cout << "culling" << endl; } else { //cout << "not culling" << endl; glDisable(GL_CULL_FACE); } //const int numQ = 1; const int numQ = (int)mOcclusionQueries.size(); //glFinish(); #if 0 //-- now issue queries for all objects for (int j = 0; j < (int)mObjects.size(); ++ j) { mOcclusionQueries[j]->BeginQuery(); RenderIntersectable(mObjects[j]); mOcclusionQueries[j]->EndQuery(); unsigned int pixelCount; pixelCount = mOcclusionQueries[j]->GetQueryResult(); mObjects[j]->mCounter += pixelCount; } #else int q = 0; //-- now issue queries for all objects for (int j = 0; j < (int)mObjects.size(); j += q) { for (q = 0; ((j + q) < (int)mObjects.size()) && (q < numQ); ++ q) { //glFinish(); mOcclusionQueries[q]->BeginQuery(); RenderIntersectable(mObjects[j + q]); mOcclusionQueries[q]->EndQuery(); //glFinish(); } //cout << "q: " << q << endl; // collect results of the queries for (int t = 0; t < q; ++ t) { unsigned int pixelCount; //-- reenable other state #if 0 bool available; do { available = mOcclusionQueries[t]->ResultAvailable(); if (!available) cout << "W"; } while (!available); #endif pixelCount = mOcclusionQueries[t]->GetQueryResult(); //if (pixelCount > 0) // cout <<"o="<mCounter += pixelCount; } //j += q; } #endif //glFinish(); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glEnable(GL_CULL_FACE); } void GlRendererBuffer::RandomViewPoint() { // do not use this function since it could return different viewpoints for // different executions of the algorithm // mViewCellsManager->GetViewPoint(mViewPoint); while (1) { Vector3 pVector = Vector3(halton.GetNumber(1), halton.GetNumber(2), halton.GetNumber(3)); mViewPoint = mViewCellsManager->GetViewSpaceBox().GetPoint(pVector); ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint); if (v && v->GetValid()) break; // generate a new vector halton.GenerateNext(); } Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4), M_PI*halton.GetNumber(5), 0.0f); mViewDirection = Normalize(Vector3(sin(dVector.x), // cos(dVector.y), 0.0f, cos(dVector.x))); halton.GenerateNext(); } void GlRenderer::RenderBox(const AxisAlignedBox3 &box) { glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Min().z ); glVertex3d(box.Min().x, box.Min().y, box.Min().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Min().y, box.Max().z ); glVertex3d(box.Max().x, box.Min().y, box.Max().z ); glVertex3d(box.Max().x, box.Max().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Max().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Max().x, box.Min().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Max().z ); glVertex3d(box.Max().x, box.Max().y, box.Max().z ); glVertex3d(box.Max().x, box.Max().y, box.Min().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Min().y, box.Min().z ); glVertex3d(box.Min().x, box.Min().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Min().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Min().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Max().z ); glVertex3d(box.Min().x, box.Min().y, box.Max().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Max().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Max().z ); glEnd(); } void GlRenderer::RenderBvhNode(BvhNode *node) { if (node->IsLeaf()) { BvhLeaf *leaf = (BvhLeaf *) node; for (int i=0; i < leaf->mObjects.size(); i++) cout << "leaf obj " << i << endl; //RenderIntersectable(mObjects[i]); } else { BvhInterior *in = (BvhInterior *)node; RenderBvhNode(in->GetBack()); RenderBvhNode(in->GetFront()); } } }