3

So, I successfully implemented picking/selection by rendering with a unique color each part I want to be selectable.

This works for geometry, but what about the text? I searched the Web a lot, but I didn't find anything connected to color picking and text.

The solution I thought was rendering some custom geometry instead of a text in the back buffer. Problem is that my scene can have different rotations (global X + local Z), so I would need to calculate every time the right position and rotation of this geometry since I need to match the position/rotation of the text, that is rendered automatically horizontal and perpendicular to the user with the glut.glutStrokeString(font, string) call.

I wonder if there is a trick also regarding text selection.

Ps: sry, I was wrong, I am not using the stroke but the glutBitmapString..

elect
  • 6,765
  • 10
  • 53
  • 119
  • What do you use for text output? Who controls the "*the right position and rotation of the text, that is rendered automatically horizontal and perpendicular to the user*" ? – Kromster Oct 24 '12 at 08:26
  • Sry, I forgot to mention it. Right now I am using the glut.glutStrokeString(font, string) – elect Oct 24 '12 at 08:30
  • 1
    What stops you from rendering the colored Text into your picking buffer? – Kromster Oct 24 '12 at 08:36
  • Shouldnt that work only when you do really select the text's body itself? I mean, for example, I would like something that even if the click happens inside an "o" (in the empty space at the center), then a selection will be triggered.. – elect Oct 24 '12 at 08:38
  • Perhaps defining some sort of bounding box would allow you to select from areas such as the middle of the "o"? – Quetzalcoatl Oct 24 '12 at 09:44

1 Answers1

3

You can calculate a bounding rectangle in screen space for your text and on a click event check if the cursor position lies in any of active bounding rectangles. Something like this:

struct brect_t { float x, y, w, h; };
struct string_t {
    void *fontID;
    const unsigned char *data;
    brect_t rect;
};

static string_t strings[MAX_STRINGS];
int stringsCount = 0;

// add new string to render queue
int stringsAdd(float x, float y, void *fontID, const unsigned char *str) {
    if (stringsCount >= MAX_STRINGS)
        return 0;

    string_t *string = strings + stringsCount++;
    string->rect.x  = x;
    string->rect.y  = y;
    string->rect.w  = glutStrokeLength(fontID, str);
    string->rect.h  = glutStrokeHeight(fontID);
    strings->fontID = fontID;
    string->data    = str;

    return 1;
}

// render all strings
void stringsRender(float r, float g, float b) {
    glColor3f(r, g, b);

    for (int i = 0; i < stringsCount; ++i) {
        const string_t *string = strings + i;

        glPushMatrix();
        glLoadIdentity();
        glTranslatef(string->rect.x, string->rect.y, 0.0f);
        glutStrokeString(string->fontID, string->data);
        glPopMatrix();
    }
}

// x,y - in model space coordinates
const string_t* stringsPick(float x, float y) {
    for (int i = 0; i < stringsCount; ++i) {
        const string_t *string = strings + i;
        const rect_t   *rect   = &string->rect;

        if (x >= rect->x &&
            y >= rect->y &&
            x <= (rect->x + rect->w) &&
            y <= (rect->y + rect->h)) {
            return string;
        }
    }

    return NULL;
}
StuGrey
  • 1,479
  • 9
  • 20
glcoder
  • 424
  • 3
  • 8
  • Hi glcoder, thanks, +1 for your code, but I would need something tested on the depth field, this means that if the text is behind some geometry it shouldnt be visible and clickable. So I guess the color picking is the only way or? – elect Oct 24 '12 at 11:12
  • @elect for color pick you can render bounding rectangle instead of string into color buffer, just make another render pass for that. Another way - raycasting and fair check all bounding volumes for intersection. Choose any! – glcoder Oct 24 '12 at 11:15
  • Damn, this is what I thought too and I wanted to avoid :D. Raycasting unfortunately is not an option for me since it looks too complicated to me and I am dealing with millions of primitives.. – elect Oct 24 '12 at 11:27
  • Ah, now I know the terminus, I didnt want that because I need a sort of billboarding.. – elect Oct 25 '12 at 13:31
  • @elect in case of color picking you need only zbuffer, nothing else is needed. – glcoder Oct 25 '12 at 14:43
  • I know, but I need geometry rendered for the text to be exactly perpendicular and horizontal to the user, regardless any rotation on my scene, exactly as in the billboarding – elect Oct 25 '12 at 14:47