Support doing coordinate transforms on the CPU
authorDavid Gow <[email protected]>
Sun, 20 Apr 2014 04:31:41 +0000 (12:31 +0800)
committerDavid Gow <[email protected]>
Sun, 20 Apr 2014 04:31:41 +0000 (12:31 +0800)
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.

bin/ipdf
src/main.h
src/real.h
src/screen.cpp
src/view.cpp
src/view.h

index 890118e..cf8ff78 100755 (executable)
Binary files a/bin/ipdf and b/bin/ipdf differ
index e866bc1..46c1544 100644 (file)
@@ -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();
        }
index 73aca6d..2a4877c 100644 (file)
@@ -6,8 +6,8 @@
 namespace IPDF
 {
 
-#define REAL_SINGLE
-//#define REAL_DOUBLE
+//#define REAL_SINGLE
+#define REAL_DOUBLE
 //#define REAL_HALF
 
 #ifdef REAL_SINGLE
index 09cd0b5..2764ef7 100644 (file)
@@ -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;
index 6a3dbdf..0354ee9 100644 (file)
@@ -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));
index 5865f9a..b099c18 100644 (file)
@@ -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;

UCC git Repository :: git.ucc.asn.au