Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > OpenGL - соответствие элементов сцены


Автор: EKoshelev 13.8.2014, 21:02
Необходимо решить такие подзадачки:
1. На экране выведено несколько точек. Делаю тычёк мышью. Надо определить какая из точек находится к мыши ближе остальных.
2. На экране выведено несколько кубиков. Определить на какой из них указывает мышь.

Наверное есть какие-то стандартные средства для решения подобных задач. Подскажите где искать.

Автор: Amp 13.8.2014, 21:33
1. Вычисляешь оконные координат точек, считаешь расстояние от них до мыши.
2. Есть разные варианты. Самый топорный, простой и устаревший вариант - selection buffer.

Автор: EKoshelev 14.8.2014, 05:19
Amp, 

1. Я так понимаю, что для вычисления оконных координат точек нужно знать матрицу (и алгоритм рассчета). Я не знаю как матрицу достать. В ней и поворот со смещением и перспектива....

2. Спасибо, посмотрю по словам selection buffer.

3. А кроме топорного и устаревшего есть что-нибудь передовое?

Автор: Amp 14.8.2014, 11:40
Оконные координаты вычисляются просто: позиция точки умножается на матрицу моделирования, затем на матрицу проекции, полученные значения приводятся к координатам вьюпорта. gluProject делает как раз эти действия. Матрицы, если ты их сам не хранишь, можешь получить через glGetFloatv.

Передового в OpenGL нет, просто выбор объектов полностью ложится на твои плечи. Например строишь луч от позиции мыши и вычисляешь его пересечение с объектами сцены. 
Есть еще достаточно простой вариант с выбором объектов по цветам http://content.gpwiki.org/index.php/OpenGL_Selection_Using_Unique_Color_IDs

Автор: EKoshelev 22.8.2014, 10:06
Вот такая функция:

Код

// По координатам точки на сцене получить её координаты на экране
void Q3dShow::getPointCoords(GLfloat fSceneX, GLfloat fSceneY, GLfloat fSceneZ, int& nX, int& nY)
{
//// Формирую матрицы (у вас будет по другому)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glPushMatrix();      
    glMultMatrixf(transform);
    glTranslatef(offsetback[12], offsetback[13], offsetback[14]);
//// Конец формирования матрицы

    GLfloat *projection = (GLfloat *)malloc(16 * sizeof(GLfloat));
    GLfloat *modelview = (GLfloat *)malloc(16 * sizeof(GLfloat));
    GLdouble *winx = new GLdouble();
    GLdouble *winy = new GLdouble();
    GLdouble *winz = new GLdouble();

    glGetFloatv(GL_PROJECTION_MATRIX, projection);
    glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
    GLdouble pr[16], mv[16];
    for (int i = 0; i < 16; i++)
    {
        pr[i] = projection[i];
        mv[i] = modelview[i];
    }
    GLint vp[4];
    vp[0] = 0;
    vp[1] = 0;
    vp[2] = width();    // ширина окна
    vp[3] = height();    // высота окна
    gluProject(fSceneX, fSceneY, fSceneZ, mv, pr, vp, winx, winy, winz);

    nX = *winx;
    nY = height() - *winy;
}

Автор: drug007 22.8.2014, 16:22
Оффтопик, конечно, но я бы под матрицы все-таки лучше бы на стеке память выделил.

Автор: EKoshelev 25.8.2014, 07:04
drug007, мне конечно дофига стыдно, но я не знаю как это.

Автор: Alexeis 2.2.2015, 14:56
Например это

Код

GLfloat *projection = (GLfloat *)malloc(16 * sizeof(GLfloat));


заменить на 

Код

GLfloat projection[16];


Если нужен указатель не обязательно выделять память в куче, просто берем адрес переменной (оператор &), а в случае массива переменная массива и так является указателем на 1й элемент. Просто передаем переменную массива как аргумент.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)