0

Drawing Lines In RV

Half as a learning excercise and half as something useful for the project I'm on, I'm trying to draw some lines on the screen. What I want to draw is a vertical line of variable width that sticks to the cursor as you move it. The vertical line would extend the height of the image.

I'm new to OpenGL but getting around Mu pretty easily. What is the most similar example provided with RV or are there some pointers someone would give to point me in the right direction?

 

Thanks RVers!

Scott

8 comments

  • 0
    Avatar
    Scott Willman

    I'm not entirely sure I understand how glVertex works. I figured it's arguments were just x and y but for some reason with the code below, the box doesn't lock to the cursor like I expected it to. Do I have a false perception of how simple it is?

     

    use rvtypes;
    use extra_commands;
    use commands;
    use gl;
    use glu;


    module: mystuff {

        class: MyStuffMode : MinorMode
        {
            
            float _do_draw;
            float _pointer_x;
            float _pointer_y;
            float _width;
            
            method: MyStuffMode (MyStuffMode;)
            {
                init("mystuff-mode",
                    [("pointer-1--drag", boxOnCursor, "go red!")],
                    nil,
                    nil);
            }
            
            method: boxOnCursor (void; Event event)
            {
                _pointer_x = event.pointer().x;
                _pointer_y = event.pointer().y;
                _width     = 10;
                
                displayFeedback("%gx%g" % (event.pointer().x, event.pointer().y));
            }
            
            method: render(void; Event event)
            {
                // int window_height = event.domain().y;
                
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                gluOrtho2D(0.0, _pointer_x, 0.0, _pointer_y);
                
                glMatrixMode(GL_MODELVIEW);
                glLoadIdentity();
                
                // Big red polygon
                glColor(Color(1,0,0,1));
                glBegin(GL_POLYGON);
                glVertex(_pointer_x - _width, _pointer_y - _width);
                glVertex(_pointer_x - _width, _pointer_y + _width);
                glVertex(_pointer_x + _width, _pointer_y + _width);
                glVertex(_pointer_x + _width, _pointer_y - _width);
                glEnd();
            }
        }
        
        
        \: createMode (Mode;)
        {
            return MyStuffMode();
        }
        
    }

  • 0
    Avatar
    Scott Willman

    Doh! It was the gluOrtho2D

     

                int window_width  = event.domain().x;
                int window_height = event.domain().y;
                
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                gluOrtho2D(0.0, window_width, 0.0, window_height);

     

  • 0
    Avatar
    Scott Willman

    I'm on the home stretch! How do I get the current scale of the rendered image? Such as when you press '2' you get an image 2:1. This is what I want, the current zoom level of the image.

    FYI, I've found 'scale()' though that seems be the zoom level of the viewer, not the image. (i.e. 'fit' creates a scale of 1)

  • 0
    Avatar
    Seth Rosenthal

    Hey Scott,

    You are too fast for us. Sorry I didn't respond more quickly. I have a few suggestions. One would be to look at some of the existing heads-up widgets like the pixel inspector. It occurred to me that you could implement your vertical line as a widget that simply draws from top to bottom of the source under the cursor and you would effectively make a widget with a very simple render loop.

    There are some advantages to having this be handled as a widget maybe.

    I think the one thing you are missing are the functions that map between image space and event space. Image space is normalized to the source image geometry while event space is the entire RV window. I made a lame hack of the inspector.mu script in RV (which creates the pixel inspector) to show you this as simply as possible.

    Find the part of the render loop in that file that looks like this:

            glBegin(GL_LINES);
            glVertex(startX, startY);
            glVertex(endX, endY);
            glEnd();

    Change it to look like this:

    #Find out the event space Y coordinate for the top and bottom of the image (x coord does not matter here, since you will be using the pointer x coord).

            let pYMin = imageToEventSpace(sName,Point(0,0)),
                pYMax = imageToEventSpace(sName,Point(0, 1));
                
            glBegin(GL_LINES);
            glVertex(startX, startY);
            glVertex(endX, endY);
            glVertex(startX,pYMin.y);
            glVertex(startX,pYMax.y);
            glEnd();



    Let me know if that helps.

    Cheers,

    Seth

  • 0
    Avatar
    Scott Willman

    Ooh that is helpful. Thanks to your example I've found eventToImageSpace which, in theory, is exactly what I need. Surprisingly it doesn't give me the results I'd expect at the right edge, like 1280 or 1556. Instead on a 1280 width image I get 2.4833...

     

    Here is the remainder of my problem. I've got two vertical lines at:

    lineA = pointer_x

    lineB = pointer_x + 20

    How do I find their equivalents in image space? The final result will be:

    imageSpace(lineB - lineA) // Measure the distance in image space between the lines.

     

    Thank you so much for your help, Seth!!!

  • 0
    Avatar
    Alan Trombla

    Hi Scott,

    This stuff is definitely a little confusing.  One key point is that you're drawing "on the view" not really "on the image", which could be zoomed or panned, etc.  So the eventual coordinates you want to feed the GL draw routines will be in Event Space, not Image Space  (you can see this in Seth's example).  Second, image space coordinates are normalized.  By default, they go from 0-1 in Y and from 0-<image aspect> in X.

    So to draw two lines that are 20 pixels apart on the screen (IE in event space), is pretty straightforward; you just get the event space x for the first line and add 20 to that number for the second line.  And if the image happens to be at 1-1 scale, those lines will also be 20 pixels apart in "image pixels".

    But if you want to draw two lines that are 20 "image pixels" apart no matter what the current zoom level is, you'll have to scale the 20-pixel offset into normalized image coordinates (using the image x resolution) and then convert that to event space for drawing.  You can see code in rvui.mu (pixelRelativeScale) that does something similar.

    But before we go further, maybe you could tell us a little more about the purpose of the tool ?

    Thanks,

    Alan

  • 0
    Avatar
    Scott Willman

    Hi Alan, thanks for taking the time to explain this. I think I have a pretty firm grasp of the concept, I just can't quite get it to work. The tool is for measuring distances along the horizontal axis.

    As a proof-of-function, I'm trying to convert from event space to image space and then back to event space. I figure that if I'm doing it right, I'll get a pretty close match. As a test, I've created a 1:1 1000x1000 tif image and it works perfectly. Oddly though, I can't get an accurate result on a Quicktime movie. Is it my code or something with Quicktimes?

     

                PixelImageInfo pInfo = imagesAtPixel(event.pointer(), nil, true).front();
                NodeImageGeometry imgGeo = nodeImageGeometry(pInfo.name, frame());
                
                float width  = imgGeo.width;
                float aspect = imgGeo.pixelAspect;
                float ex     = _pointer_x;
                float ix     = pInfo.px;
                
                float normImg = ix / (width * aspect);
                vector float[2] newX = imageToEventSpace(pInfo.name, Point(normImg, 0));
                
                displayFeedback("Width: %g Aspect: %g pointer: %g toImage: %g backToEvent: %g" % (width, aspect, _pointer_x, ix, newX.x));

  • 0
    Avatar
    Jon Morley

    Can you share the results you are getting with the Quicktimes? Is it possible that the orientation is inverted or something like that? Please tell us what you are seeing with the Quicktime movies.

    Thanks,

    Jon

Please sign in to leave a comment.