Я знаю, что режим выбора OpenGL устарел и никогда не ускорялся HW, за исключением нескольких блоков SGI и графических процессоров 3DLabs. Но я не могу избавиться от него (не мой код). Ниже его код C ++:
void GLWidget::Selection(int x,int y) // This Is Where Selection Is Done
{
GLint viewport[4];
glSelectBuffer(BUFSIZE,selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT,viewport);
gluPickMatrix(x,viewport[3]-y,5,5,viewport); //defining the picking matrix
gluPerspective(fov,ratio,0.1f,1000);
glMatrixMode(GL_MODELVIEW);
glInitNames();
glPushName(1); //Pushing names on the stack
glutSolidTorus(1, 2, 55, 55); //Some draw in GL_SELECT mode
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(2);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(3);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2); //public members
glTranslatef(5.0f,1,5.0f);
glPopName();
int hits;
// restoring the original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
// returning to normal rendering mode
hits = glRenderMode(GL_RENDER);
// if there are hits process them
if (hits != 0){
qDebug() << "Found " << hits << " hit(s)";
processHits(hits,selectBuf);
}
}
Это метод processHits
void GLWidget::processHits (GLint hits, GLuint buffer[]) //Some prints
{
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < hits; i++) {
names = *ptr;
ptr++;
if (*ptr < minZ) {
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
}
ptr += names+2;
}
qDebug() << "Nearest: ";
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++) {
qDebug() << *ptr ;
}
}
Selection () вызывается с помощью события * (GLWidget наследуется от QGLWidget (QT 4.8)).
Таким образом, только когда я нажимаю правую кнопку мыши, я «рисую» объекты в буфере и помещаю их имена в стек.
void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
if (event->buttons() & GLUT_RIGHT_BUTTON){
Selection(event->x(),event->y());
}
}
В то время как метод paintGL ()
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glViewport (0, 0, w_screen, h_screen);gluLookAt(objCamera->mPos.x, objCamera->mPos.y, objCamera->mPos.z,
0, objCamera->mView.y, 0,
objCamera->mUp.x, objCamera->mUp.y, objCamera->mUp.z);
glutSolidTorus(1, 2, 55, 55); //draw some objects
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2);
glTranslatef(5.0f,1,5.0f);
glTranslatef(-15.0f,-3,-15.0f);
}
В настоящее время, с помощью этого кода, я могу выбрать объект и получить его идентификатор, и если их больше по тем же координатам xy, я могу получить ближайший (по идентификатору).
Итак, теперь у меня есть 3 объекта с 3 разными идентификаторами (1-2-3).
Тот, у которого ID = 3, имеет фиксированный размер. Мой вопрос: как использовать буфер для извлечения третьего тора и изменения его размера, изменяя RADIUS1, RADIUS2, complex1, complex2?
Может ли кто-нибудь из вас написать небольшой пример?
Пусть я, когда происходит попадание, просто использую имя попадания в стек (данное с помощью glPushName), которое должно каким-то образом ссылаться на объект (может быть, со строковым открытым членом, который содержит имя), так что я могу изменить его свойства?
Вам нужно будет хранить свойства каждого объекта самостоятельно. Когда вы помещаете имя в стек имен, все, что вы делаете, это добавляете дополнительные данные к каждому фрагменту, чтобы вы могли эффективно определить, откуда оно появилось позже.
Вы, вероятно, захотите создать структуру вроде {float rad1, rad2, complex1, complex2; } для хранения значений для каждого тора. Как только вы узнаете идентификатор выбранного объекта, перейдите в свой массив указанной структуры и измените значения для соответствующего объекта. Каждый раз, когда вы рисуете свою сцену, просто бегите через этот массив структур.
Других решений пока нет …