sciapp / gr

GR framework: a graphics library for visualisation applications
Other
329 stars 54 forks source link

gks window size and resolution scaling #55

Closed nilsbecker closed 5 years ago

nilsbecker commented 6 years ago

the way output resolution scaling works is nice in principle: the user sets a desired resolution and that is then fixed; the output window size scales but the resolution stays the same. this requires mapping and interpolation of the rendering resolution to the screen.

this interpolation works best when the ratio of rendered pixes to screen pixes is simple. e.g. 2:1 or 1:1. i could not find an option in gr3 to set the window size to ensure that this happens -- is this my mistake or is it missing from the api?

FlorianRhiem commented 6 years ago

When using GR3, you need to set the rendering resolution as part of the parameters for gr3_export, gr3_getimage or gr3_drawimage. If you are using gr3_drawimage in combination with a GUI toolkit or GR/GKS, you should set this resolution to the width and heights of the area which the image will be drawn on. How to determine these depends on the GUI toolkit you are using and the geometry inside your UI.

nilsbecker commented 6 years ago

thanks. in my case this is on os x. i use gr3_drawimage in a draw method of my Scene class like this:

    def draw(self):
        v, s = self.viewport, self.view_size
        gr.setviewport(*self.viewport)
        gr3.drawimage(
                v[0], v[1], v[2], v[3],
                s[0], s[1],
                gr3.GR3_Drawable.GR3_DRAWABLE_GKS)
        gr.updatews()

which i initialize with

            ...
            viewport=(0, 1, 0, 1),
            view_size=(500, 500),

the view_size parameter seems to set the raster resolution of the output. the window size can then still be changed by dragging the window corners etc. what other parameter will set the window size in this case?

FlorianRhiem commented 6 years ago

For the GR3 part: When your window changes size you need to call drawimage with updated width and height, so for GR3 to work correctly here you need to make sure your self.view_size variable is up to date. This will work independent of whether you use GR like you do here or Qt, wxWidgets, etc.

There currently is no function to query the window size for the default GKSTerm workstation on macOS. If you use a GUI toolkit like Qt, you will be able to query the width and height and use those.

nilsbecker commented 5 years ago

is is still the case that the GKSTerm offers no way to check or set its window size? i am currently trying to get good-looking output on GKSTerm and i still don't know how to make view_size and the GKS window size correspond to each other.

a workaround would be some way to start GKSTerm with a defined window size. then i could just leave that alone for the duration of the visualization..

nilsbecker commented 5 years ago

alternatively, is there a simple example of how to set up GR with another framework, which will work on OS X?

FlorianRhiem commented 5 years ago

Yes, there still is no inqwsviewport. You can use gr.setwsviewport to set the window size (in meters, gr.inqdspsize can help with the conversion).

For an example on using another framework, perhaps try the example for PyQt5 and the gr.pygr.GRWidget (there also PyQt4 and PySide versions of this example). Aside of setting up the GRWidget, these examples use buttons and display actual data, so if you want I can build a more minimal version tomorrow.

nilsbecker commented 5 years ago

thanks, i'll try first with the gr functions for setting size. i had a look at mogli, where glfw is used, and i got that running almost satisfactorily as well. it did look simple to use.

nilsbecker commented 5 years ago

ok, so on my imac,

gr.inqdspsize()
Out[6]: [0.5992995301699309, 0.3402418553551963, 2560, 1440]

the pixel values are half the actual resolution, which might be due to retina. the meter values are probably incorrect; they correspond neither to half nor to the full screen dimensions. also, their ratio is slightly different from 2560/1440

if i set

 gr.setwsviewport(0,0.599,0,0.34)

i get a window which is quite big but does not fill the width of the screen; the height appears to be the height of the screen without the menu bar.

anyway. i really want mouse interaction for camera turning, panning and zooming. so i guess i need to use some framework other than gksterm. in mogli there is example code using glfw. to me this seems easier than using qt5 -- even though the example linked above looks not too complex, qt5 just seems too big.

what would be your suggested simplest/fastest way to get 1. defined window size 2. mouse interactivity to set the camera?

FlorianRhiem commented 5 years ago

Hmm, I get very similar display size values (0.5965504497563073, 0.33555962798792294, 2560, 1440), when using my 27-inch Thunderbolt Display, which actually is the correct size in meters and pixels. What size is the display of your iMac?


If you only need mouse and keyboard interaction with a GR3 scene, glfw will work fine. Otherwise I would recommend Qt.

Here's the usual glfw example code combined with a fairly minimal GR3 setup:

import glfw
import gr3

def main():
    # Initialize the library
    if not glfw.init():
        return
    # Create a windowed mode window and its OpenGL context
    window = glfw.create_window(640, 480, "glfw + gr3", None, None)
    if not window:
        glfw.terminate()
        return

    # Make the window's context current
    glfw.make_context_current(window)

    # Set up GR3 scene
    gr3.setbackgroundcolor(1, 1, 1, 0)
    gr3.drawspheremesh(1, (0, 0, 0), (1, 1, 1), [1])

    # Loop until the user closes the window
    while not glfw.window_should_close(window):
        # Set camera position and draw image
        gr3.cameralookat(
            0, 0, 3,
            0, 0, 0,
            0, 1, 0
        )
        gr3.drawimage(0, 640, 0, 480, 640, 480, gr3.GR3_Drawable.GR3_DRAWABLE_OPENGL)
        # Swap front and back buffers
        glfw.swap_buffers(window)

        # Poll for and process events
        glfw.poll_events()

    glfw.terminate()

if __name__ == "__main__":
    main()
nilsbecker commented 5 years ago

about the display: i have a 27'' retina iMac. the physical resolution is 5120x2880, but i think this is treated as 2560x1440 by the os? not sure exactly how that works. the physical dimensions seem to be correct after all -- i was convinced i could judge by eye that the screen is bigger than 60x34cm but this is what it is.

thanks for the glfw example, i'm trying that route now. have already started taking inspiration from mogli.

nilsbecker commented 5 years ago

hi, i almost got it working with glfw. the only thing that is still off is that i get a display only in the lower left corner of the glfw window -- everything is scaled down by a factor 1/2 it seems. i get the same problem if i just fun the mogli example from the github repo.

again i suspect that this has to do with the implicit doubling that retina does. will play around a but with what of widht/height/size has to get a factor of 2...

Update: i need

        gr3.drawimage(0, 2*width, 0, 2*height,
                      width, height, 
                      gr3.GR3_Drawable.GR3_DRAWABLE_OPENGL)
FlorianRhiem commented 5 years ago

Ah, yes, you need to consider Retina. It's probably best to query the width and height from glfw.get_framebuffer_size().

nilsbecker commented 5 years ago

that works, thanks!

danielkaiser commented 5 years ago

We are closing this issue due to inactivity. Please reopen the issue and let us know if its cause still persists with the current version of GR.