Выбрать главу

Мне кажется, проблем с разбором классов возникнуть не должно. Только не нужно забывать про сдвиг положения элемента интерфейса на 0.5 относительно его реального положения (чтобы центры текселей текстуры совпадали с пикселями экрана при текстурировании, подробнее можно посмотреть в DirectX SDK, топик "Directly Mapping Texels to Pixels"). Это устраняет замыливание интерфейсных элементов при фильтрации, и, кроме того, позволяет отображать интерфейс вообще без фильтрации, что сильно улучшает четкость изображения.

Список и краткое назначение классов:

Static — это класс для отображения статичной плоской графической информации. Практически все его предназначение - это рисование плоского экранного спрайта в заданных экранных координатах.

Button — это класс для отображения кнопки. Он перекрывает функциональность Static'а, кроме того он отслеживает положение курсора и состояние левой кнопки мыши, определяет момент щелчка по кнопке и запускает на выполнения функцию, которая поставлена в соответствие этому экземпляру класса. Кроме того отображается в различных состояниях:

- в состоянии NORMAL — это обычно состояние (курсор не находится над кнопкой),

- в состоянии FOCUS — курсор наведен,

- в состоянии PRESSED — курсор наведен и нажата левая кнопка,

- в состоянии DISABLED — кнопка отключена.

Animate — используется для отображения анимированной информации. В примере мы выводим огонь. Но в реальном приложении это может быть анимированная кнопка. Класс потребует некоторого расширения, но останется в принципе тем же.

И последнее,

Edit — это аналог CEdit из библиотеки MFC. Перехватывает "фокус", позволяет вводить информацию, удалять BackSpace'ом и Delete'ом. В общем, это тоже класс, который требует доработки, а также, может быть некоторой специализации. В исходнике на русском языке кратко изложено, что я думаю по этому поводу. Например, можно совместить классы Edit и CConfigFile и сделать, чтобы строчка из Edit могла быть обработана CConfigFile'ом (это очень легкая задача). Тогда можно будет легко написать консоль приложения.

Вообще, все классы, которые приведены — они как бы классы примеров, то есть не введен класс CheckBox, RadioButton, AnimateButton или ProgressBar, но не потому, что их реализация сложна, а как раз потому, что она очень похожа на реализации уже приведенных классов. Какие конкретно классы будут реализованы зависит, в основном, от необходимости и требований конкретного приложения.

Переходим к ландшафту.

В сети очень много информации по рисованию ландшафта, здесь мы отметим только принципиальные моменты, которые следует учитывать при проектировании ландшафта.

Прежде всего, нужно ориентироваться на блочную структуру, организации сцены. То есть нужно стараться, чтобы у вас были готовые небольшие локальные кусочки поверхности, которые вы можете рисовать отдельно. При этом, конечно, не стоит забывать, что по скорости рисовать два фрагмента по 400 треугольников ничуть не медленнее, чем рисовать два фрагмента по 200 треугольников. Поэтому размер фрагмента должен быть достаточно большим. При этом достаточно важно накладываемое требование на локальность кусочков. Наилучший вариант - это квадрат, но, к сожалению, квадратная организация фрагментов неоптимальна. Вы должны решить, что для вас в данный момент важнее, вывод поверхности максимально быстро или у вас есть какие-нибудь другие приоритеты (например, организовать квадратную фрагментацию гораздо проще). Дело в том, что вы будете использовать кэш видеокарты только при короткой длине линии (до восьми вершин). Вы должны захватить как можно больше вершин в кэше при обратном проходе (за счет этого можно практически вдвое увеличить скорость вывода ландшафта). Никакой практической сложности при выводе ландшафта нет. Только нужно не забывать, что линии нужно соединять без лишних треугольников, поэтому между переходами приходится вставлять вырожденные треугольники (этот механизм используется для увеличения длины линии заданной через TriangleStrip). Такие вырожденные треугольники практически бесплатны, ведь трансформированные вершины в момент использования обычно уже находятся в кэше видеокарты, и даже если их там нет, то они будут выбраны из кэша при обратном проходе, а поскольку они вырождены, то рисуются они только одной линией. То есть нам получается значительно выгоднее нарисовать лишние треугольники, но не разрывать цепочку (несколько вызовов DIP c маленьким количеством треугольников обрабатываемом при каждом вызове). Естественно, что каждому фрагменту нужно ставить в соответствие две переменные — расстояние до центра и флаг видимости (которые можно вычислять любым способом, главное — чтобы было правильно :) ). Обычно вычисляют процессором, но, например, можно для этого использовать функцию ProcessVertices (которая для этого и была создана, она, правда тоже считает процессором, но, вроде как, использует SSE или 3DNow!).