From: David Gow Date: Sun, 20 Apr 2014 04:31:41 +0000 (+0800) Subject: Support doing coordinate transforms on the CPU X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=6ad7439e8ebf969fcd2d3a710a4b16e2b1ee131f;p=ipdf%2Fcode.git Support doing coordinate transforms on the CPU So because OpenGL (by default at least), does everything with 32-bit IEEE floats, even when our "Real" type is a double, we lost precision when rendering it. This commit adds support for running the coordinate transform on the CPU using the Real datatype, and only truncating the results, making things work properly with doubles. This will be slower on documents with a large number of objects, but there's no real difference in our unoptimized code at the moment. Right-click to switch between CPU and GPU transforms. --- diff --git a/bin/ipdf b/bin/ipdf index 890118e..cf8ff78 100755 Binary files a/bin/ipdf and b/bin/ipdf differ diff --git a/src/main.h b/src/main.h index e866bc1..46c1544 100644 --- a/src/main.h +++ b/src/main.h @@ -31,6 +31,14 @@ inline void MainLoop(Document & doc, const Rect & bounds = Rect(0,0,1,1), const { static bool oldButtonDown = false; static int oldx, oldy; + if (buttons > 1 && !oldButtonDown) + { + oldButtonDown = true; + view.ToggleGPUTransform(); + oldx = x; + oldy = y; + return; + } if (buttons && !oldButtonDown) { // We're beginning a drag. @@ -65,6 +73,14 @@ inline void MainLoop(Document & doc, const Rect & bounds = Rect(0,0,1,1), const view.Render(); scr.DebugFontPrintF("[CPU] Render took %lf ms (%lf FPS)\n", (SDL_GetPerformanceCounter() - init_time)* 1000.0/SDL_GetPerformanceFrequency(), SDL_GetPerformanceFrequency()/(SDL_GetPerformanceCounter() - init_time)); scr.DebugFontPrintF("View bounds: (%f, %f) - (%f, %f)\n", view.GetBounds().x, view.GetBounds().y, view.GetBounds().w, view.GetBounds().h); + if (view.UsingGPUTransform()) + { + scr.DebugFontPrint("Doing coordinate transform on the GPU.\n"); + } + else + { + scr.DebugFontPrint("Doing coordinate transform on the CPU.\n"); + } scr.Present(); init_time = SDL_GetPerformanceCounter(); } diff --git a/src/real.h b/src/real.h index 73aca6d..2a4877c 100644 --- a/src/real.h +++ b/src/real.h @@ -6,8 +6,8 @@ namespace IPDF { -#define REAL_SINGLE -//#define REAL_DOUBLE +//#define REAL_SINGLE +#define REAL_DOUBLE //#define REAL_HALF #ifdef REAL_SINGLE diff --git a/src/screen.cpp b/src/screen.cpp index 09cd0b5..2764ef7 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -82,7 +82,7 @@ bool Screen::PumpEvents() m_last_mouse_y = evt.button.y; if (m_mouse_handler) { - m_mouse_handler(evt.button.x, evt.button.y, evt.button.state, 0); + m_mouse_handler(evt.button.x, evt.button.y, evt.button.state?evt.button.button:0, 0); } break; case SDL_MOUSEWHEEL: @@ -100,6 +100,7 @@ bool Screen::PumpEvents() filename[0] = (char)evt.key.keysym.sym; ScreenShot(filename); } + break; } default: break; diff --git a/src/view.cpp b/src/view.cpp index 6a3dbdf..0354ee9 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -35,6 +35,17 @@ void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt) m_bounds.h *= scaleAmt; } +Rect View::TransformToViewCoords(const Rect& inp) const +{ + Rect out; + out.x = (inp.x - m_bounds.x) / m_bounds.w; + out.y = (inp.y - m_bounds.y) / m_bounds.h; + + out.w = inp.w / m_bounds.w; + out.h = inp.h / m_bounds.h; + return out; +} + void View::DrawGrid() { // Draw some grid lines at fixed pixel positions @@ -74,7 +85,14 @@ void View::Render() glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(Float(m_bounds.x), Float(m_bounds.x)+Float(m_bounds.w), Float(m_bounds.y) + Float(m_bounds.h), Float(m_bounds.y), -1.f, 1.f); + if (m_use_gpu_transform) + { + glOrtho(Float(m_bounds.x), Float(m_bounds.x)+Float(m_bounds.w), Float(m_bounds.y) + Float(m_bounds.h), Float(m_bounds.y), -1.f, 1.f); + } + else + { + glOrtho(0,1,1,0,-1,1); + } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -89,7 +107,15 @@ void View::Render() { if (m_document.m_objects.types[id] != RECT_FILLED) continue; - Rect obj_bounds = m_document.m_objects.bounds[id]; + Rect obj_bounds; + if (m_use_gpu_transform) + { + obj_bounds = m_document.m_objects.bounds[id]; + } + else + { + obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]); + } glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y)); glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y)); glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y) + Float(obj_bounds.h)); @@ -102,7 +128,15 @@ void View::Render() { if (m_document.m_objects.types[id] != RECT_OUTLINE) continue; - Rect obj_bounds = m_document.m_objects.bounds[id]; + Rect obj_bounds; + if (m_use_gpu_transform) + { + obj_bounds = m_document.m_objects.bounds[id]; + } + else + { + obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]); + } glBegin(GL_LINE_LOOP); glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y)); glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y)); diff --git a/src/view.h b/src/view.h index 5865f9a..b099c18 100644 --- a/src/view.h +++ b/src/view.h @@ -10,7 +10,7 @@ namespace IPDF { public: View(Document & document, const Rect & bounds = Rect(0,0,1,1), const Colour & colour = Colour(0.f,0.f,0.f,1.f)) - : m_document(document), m_bounds(bounds), m_colour(colour) {} + : m_document(document), m_bounds(bounds), m_colour(colour), m_use_gpu_transform(false) {} virtual ~View() {} void Render(); @@ -18,10 +18,16 @@ namespace IPDF void Translate(Real x, Real y); void ScaleAroundPoint(Real x, Real y, Real scaleAmt); + Rect TransformToViewCoords(const Rect& inp) const; + const Rect& GetBounds() const { return m_bounds; } + + const bool UsingGPUTransform() const { return m_use_gpu_transform; } + void ToggleGPUTransform() { m_use_gpu_transform = (!m_use_gpu_transform); } private: void DrawGrid(); + bool m_use_gpu_transform; Document & m_document; Rect m_bounds; Colour m_colour;