#include "SceneQuery.h" #include "glInterface.h" #include "Vector3.h" #include "Camera.h" #include "SceneQuery.h" #include "RenderTraverser.h" #include "FrameBufferObject.h" #include "RenderState.h" #include "SceneEntity.h" #include #include #ifdef _CRT_SET #define _CRTDBG_MAP_ALLOC #include #include // redefine new operator #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif using namespace std; const static int texWidth = 2048; const static int texHeight = 2048; 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("sceneQuery.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; } ilEnable(IL_FILE_OVERWRITE); if (!ilSaveImage(filename)) { cerr << "TGA write error " << ilGetError() << endl; } stopil(); cout << "exported depth buffer" << endl; } SceneQuery::SceneQuery(const AxisAlignedBox3 &sceneBox, RenderTraverser *renderer, RenderState *state): mSceneBox(sceneBox), mDepth(NULL), mRenderState(state) { Prepare(renderer); } bool SceneQuery::CalcIntersection(Vector3 &pt) { const int px = (mSceneBox.Max(0) - pt.x) * (texWidth - 1) / mSceneBox.Size(0); const int py = (mSceneBox.Max(1) - pt.y) * (texHeight - 1) / mSceneBox.Size(1); const float d = mDepth[px + py * texHeight]; static float depth = d; if (d > .0f) { // 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 * .5f; const float ylen = mSceneBox.Size().y * .5f; Vector3 pos = Vector3(mSceneBox.Center().x, mSceneBox.Center().y, mSceneBox.Max().z); FrameBufferObject *fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32, true); fbo->AddColorBuffer(ColorBufferObject::RGBA_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST, ColorBufferObject::FILTER_NEAREST); fbo->Bind(); glDrawBuffers(1, mrt); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, texWidth, texHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); OrthoCamera *orthoCam = new OrthoCamera(xlen, -xlen, ylen, -ylen, .0f, mSceneBox.Size().z); orthoCam->SetDirection(Vector3(0, 0, -1)); orthoCam->SetPosition(pos); orthoCam->SetupViewProjection(); //glOrtho(xlen, -xlen, ylen, -ylen, 0.0f, mSceneBox.Size().z); glMatrixMode(GL_MODELVIEW); //orthoCam->SetupCameraView(); mDepth = new float[texHeight * texWidth]; Camera *oldCam = renderer->GetCamera(); renderer->SetCamera(orthoCam); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); // hack: use highest lod level for trees (billboards) LODLevel::InitFrame(Vector3(1e6f)); // forward rendering mRenderState->SetRenderTechnique(0); // temporarilly switch off renderer->SetRenderDynamicObjects(false); renderer->RenderScene(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); renderer->SetCamera(oldCam); // temporarilly switch off renderer->SetRenderDynamicObjects(true); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); FrameBufferObject::Release(); GrabDepthBuffer(mDepth, fbo->GetDepthTex()); ExportDepthBuffer(mDepth); PrintGLerror("grab depth"); DEL_PTR(fbo); DEL_PTR(orthoCam); } }