#include "SceneQuery.h" #include "glInterface.h" #include "Vector3.h" #include "Camera.h" #include "SceneQuery.h" #include "RenderTraverser.h" #include "FrameBufferObject.h" #include #include using namespace std; const static int texWidth = 2048; const static int texHeight = 2048; static GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT}; static void PrintGLerror(char *msg) { GLenum errCode; const GLubyte *errStr; if ((errCode = glGetError()) != GL_NO_ERROR) { errStr = gluErrorString(errCode); fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg); } } static void startil() { ilInit(); assert(ilGetError() == IL_NO_ERROR); } static void stopil() { ilShutDown(); assert(ilGetError() == IL_NO_ERROR); } namespace CHCDemoEngine { static void GrabDepthBuffer(float *data, GLuint depthTexture) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, depthTexture); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); } static void ExportDepthBuffer(float *data) { startil(); ILstring filename = ILstring("depth.tga"); ilRegisterType(IL_FLOAT); const int depth = 1; const int bpp = 1; if (!ilTexImage(texWidth, texHeight, depth, bpp, IL_LUMINANCE, IL_FLOAT, data)) { cerr << "IL error " << ilGetError() << endl; stopil(); return; } if (!ilSaveImage(filename)) { cerr << "TGA write error " << ilGetError() << endl; } stopil(); cout << "exported depth buffer" << endl; } SceneQuery::SceneQuery(const AxisAlignedBox3 &sceneBox, RenderTraverser *renderer): mSceneBox(sceneBox), mDepth(NULL) { Prepare(renderer); } bool SceneQuery::CalcIntersection(Vector3 &pt) { const int px = (pt.x - mSceneBox.Min(0)) * (texWidth - 1) / mSceneBox.Size(0); const int py = (pt.y - mSceneBox.Min(1)) * (texHeight - 1) / mSceneBox.Size(1); float d = mDepth[px + py * texHeight]; static float depth = d; if (d > 0) { // temporal smoothing of depth values const float x = .5f; depth = d * x + depth * (1.0f - x); const float offs = mSceneBox.Size(2) * 5e-2f; pt.z = mSceneBox.Max().z - mSceneBox.Size().z * depth + offs; return true; } return false; } void SceneQuery::Prepare(RenderTraverser *renderer) { cout << "Preparing scene queries" << endl; const float xlen = mSceneBox.Size().x * 0.5f; const float ylen = mSceneBox.Size().y * 0.5f; Camera *orthoCam = new Camera(xlen, ylen); orthoCam->SetOrtho(true); orthoCam->SetNear(0.0f); orthoCam->SetDirection(Vector3(0, 0, 1)); cout << orthoCam->GetDirection() << endl; Vector3 pos = Vector3(mSceneBox.Center().x, mSceneBox.Center().y, mSceneBox.Max().z); orthoCam->SetPosition(pos); FrameBufferObject *fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32, true); fbo->AddColorBuffer(ColorBufferObject::BUFFER_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST, false); fbo->Bind(); glDrawBuffers(1, mrt); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, texWidth, texHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glOrtho(+xlen, -xlen, ylen, -ylen, 0.0f, mSceneBox.Size().z); glMatrixMode(GL_MODELVIEW); glPushMatrix(); orthoCam->SetupCameraView(); mDepth = new float[texHeight * texWidth]; renderer->RenderScene(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); FrameBufferObject::Release(); GrabDepthBuffer(mDepth, fbo->GetDepthTex()); ExportDepthBuffer(mDepth); PrintGLerror("grab"); DEL_PTR(fbo); DEL_PTR(orthoCam); } }