if(root->child!=NULL) traverse(root->child); glPopMatrix();
if(root->sibling!=NULL) traverse(root->sibling);
}
При обработке узла, указатель на который не равен NULL, сначала в стеке сохраняется текущая матрица преобразования, для чего вызывается функция glPushMatrix( ). Затем матрица, хранящаяся в структуре узла, модифицирует текущую матрицу вида (предполагается, что соответствующий режим работы с матрицами установлен раньше). Далее формируется изображение компонента, для чего вызывается функция, указатель на которую хранится в члене f структуры узла. Затем следует рекурсивное обращение к этой же функции, но для дочернего узла. Обращаю ваше внимание на то, что перед обращением к обработке дочернего узла в матрице вида уже установлена матрица преобразования текущего узла и именно она будет использована при формировании матрицы вида для отображения дочернего узла. А вот перед переходом к обработке "братского" узла нужно восстановить прежнюю матрицу вида - извлечь ее из стека с помощью функции glPopMatrix( ). Если при обработке узла нужно устанавливать новые значения атрибутов, то прежние следует сначала запомнить в стеке, а затем восстановить. Лучше всего это делать в функции отображения компонента либо выполнять эти операции синхронно с записью/извлечением матрицы вида.
Одна из наиболее привлекательных особенностей рассмотренного метода программной реализации обхода такого иерархического дерева состоит в том, что он никак не связан со структурой конкретной модели. В результате в программе можно использовать родовую функцию отображения с обратным вызовом, которая имеет следующий вид:
void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity();
traverse(&torso_node);
glutSwapBuffers();
}
Файл figuretree.c текста программы отображения подвижной фигурки киборга, в которой используется рекурсивная функция обработки узлов дерева, читатель найдет на ftp-сервере по адресу ftp.cs.unm.edu в каталоге pub/angel/BOOK. Работая с этой программой, пользователь может изменять углы в сочленениях фигурки, вызывая те или иные команды меню, и наблюдать на экране, как движется фигурка. Поэтому все управление динамикой изображения сосредоточено в функции обработки сообщений мыши. Здесь изменяются углы в сочленениях, заново формируются матрицы преобразования для соответствующих узлов, а затем вызывается функция отображения: