ColorToGL (Canvas.Pixels [X,Y], R, G, B) ;
If (R о 0) and (B = 0) then
ShowMessage ('Выбран красный треугольник');
Здесь для определения составляющих цвета пиксела вызывается пользовательская процедура, знакомая по главе 1.
glRotatef (AngleXYZ [1], 1, 0, 0);
glRotatef (AngleXYZ [2], 0, 1, 0);
glRotatef (AngleXYZ [3], 0, 0, 1);
If flgSquare then glCallList (1); // рисуем площадку (плоскость узла)
If flgOc then OcXYZ; // рисуем оси
If flgLight then begin // рисуем источник света
glTranslatef (PLPosition^ [1], PLPosition^ [2], PLPosition^ [3]);
gluSphere (ObjSphere, 0.01, 5, 5);
glTranslatef (-PLPosition^ [1], -PLPosition^ [2], -PLPosition^ [3]);
end;
glScalef (CoeffX, CoeffY, CoeffZ);
glTranslatef (0.0, 0.0, SmallB);
glCallList (3); // пружина
glCallList (10); // дырки в плите под болты
glCallList (5); // плита
glRotatef (AngleX, 1.0, 0.0, 0.0);
glRotatef (AngleY, 0.0, 1.0, 0.0);
glTranslatef (0.0, 0.0, Smallh);
glCallList (4); // диск
glCallList (8); // первый болт
glCallList (9); // второй болт
glRotatef (AngleZ, 0.0, 0.0, 1.0);
glCallList (2); // шпильковерт со шпинделем
glCallList (6); // патрон
glCallList (7); //деталь
glPopMatrix;
// конец работы SwapBuffers(DC);
end;
Конечно, вызываемые подряд списки можно также объединить, и после этого код вообще уложится в десяток строк.
В примере для определения цвета пиксела под курсором используются средства Delphi - прямое обращение к цвету пиксела формы.
В проекте из подкаталога Ех02 делается все то же самое, но цвет пиксела определяется с помощью команды OpenGL:
var
wrk : Array [0..2] of GLUbyte; begin
glReadPixels (X, Y, 1, 1, GL_RGB, GLJJNSIGNED_BYTE, @wrk);
If (wrk [0] о 0) and (wrk [2] = 0) then
ShowMessage ('Выбран красный треугольник')
else
If (wrk [0] = 0) and (wrk [2] <> 0) then
ShowMessage ('Выбран синий треугольник')
else
ShowMessage ('Ничего не выбрано');
end;
Выбор объектов, основанный на определении цвета пиксела под курсором, немногим отличается от простого анализа координат точки выбора. Достоинства такого метода - простота и высокая скорость. Но есть и недостатки:
Следующий метод выбора похож на предыдущий: элементы, раскрашенные в уникальные цвета, рисуются в заднем буфере кадра, без вызова команды SwapBuffers. Для выбора элементов анализируем цвет заднего буфера в позиции, в которой осуществляется выбор. В заднем буфере элементы рисуются без текстуры и при выключенном источнике света, чтобы не портить чистые цвета.
Обратимся для ясности к проекту из подкаталога Ех03, где рисуются два треугольника одинакового цвета, при нажатии кнопки сообщается, какой треугольник выбран, левый или правый.
В процедуре перерисовки окна после команды SwapBuffers код рисования треугольников повторяется, однако каждый треугольник раскрашивается в уникальные цвета. Цвет фона для простоты дальнейших манипуляций задается черным.
Обработка нажатия кнопки начинается так:
wglMakeCurrent(Canvas.Handle, hrc);
glReadPixels(X, ClientHeight - Y, I, I, GL_RGB, GL_UNSIGNED_BYTE, @Pixel);
If (Pixel [0] <> 0) and (Pixel [2] = 0)
then ShowMessage ('Выбран левый треугольник');
To есть считываем пиксел в текущем, заднем, буфере кадра в позиции курсора, для чего необходимо предварительно установить контекст воспроизведения. Массив, хранящий цвета пиксела - массив трех элементов типа GLbyte.
Для разнообразия в этом примере я не занимаю контекст воспроизведения один раз на все время работы приложения, а делаю это дважды: один раз при перерисовке окна для воспроизведения сцены и второй раз при нажатии кнопки мыши для того, чтобы воспользоваться командами OpenGL чтения пиксела. Каждый раз после работы контекст, конечно, освобождается.
Чтобы не сложилось впечатление, что такой метод применим только для плоскостных построений, предлагаю посмотреть пример из подкаталога Ех04, где рисуются сфера и конус из одного материала и осуществляется выбор между ними. Можете перенести вызов команды SwapBuffers в конец кода перерисовки окна, чтобы увидеть, как сцена выглядит в заднем буфере.