[ главная ]   [ рейтинг статей ]   [ справочник радиолюбителя ]   [ новости мира ИТ ]



Ответов: 0
25-02-12 07:01







   Web - программирование
PHP


ASP






XML



CSS

SSI





   Программирование под ОС











   Web - технологии








   Базы Данных









   Графика






Данные




Графика / Direct x /

Вычисление нормалей к поверхностям

В прошлом уроке, там, где я показывал структуризацию и классификацию проекта, я привожу пример трехмерного ландшафта. Сам алгоритм построения ландшафта я опишу в последующих уроках (посвященных работе с ландшафтами), сейчас же нас интересует, как производится расчет нормалей для полигонов, составляющих поверхность ландшафта. Те кто запускал пример, должны были видели, как производится освещение. В тексте программы, при генерации ландшафта, установка нормалей не производится, единственное упоминание о нормалях содержится в вызове функции GenerateNormals () , которую я создал специально для расчета нормалей для ландшафта (и содержится пока в классе трехмерных объектов, я думаю, потом она будет находиться немного в другом месте).

Давайте сначала рассмотрим теорию нахождения нормали к плоскости по заданным точкам (у меня частенько спрашивают этот вопрос), а затем рассмотрим, как это реализовать в Direct3D8 (точнее, как это сделал я).

---------------------------------------------

Так что же такое нормаль? Нормаль представляет направление в пространстве и имеет параметры (x,y,z), как и любой вектор. Особенностью нормали можно назвать то, что ее длина всегда равна 1. То есть:

Sqrt(x2+y2+z2) = 1

Как рассчитывается нормаль? Для начала возьмем три точки (a,b и c). По этим точкам необходимо вычислить вектора p (из точки a в b) и q (из a в с):

p = b - a
q = c - a

Получив два этих вектора, вычисляем нормаль как перекрестное произведение векторов p и q с нормализацией результата. Это можно представить в псевдокоде как:

n = Cross(p, q);
Normalize(n);

Для нормализации результата необходимо разделить каждый параметр вектора на его длину, которая вычисляется как:

length = Sqrt(x2+y2+z2);

---------------------------------------------

Это теория. Теперь как это сделал я.

У нас имеется массив точек, представляющих вершины и массив индексов, показывающий как необходимо обходить эти вершины (т.е. фактически построение полигонов). Нам необходимо пробежаться по всем индексам из массива индексов, получить значения координат для трех точек составляющих отдельный полигон, затем рассчитать вектора и получить нормаль (и затем присвоить ее нужной вершине). Вот как это выглядит :

здесь :

- p_ObjInd - массив индексов
- p_ObjVert - массив вершин
- dwNumIndecies - количество индексов
- v1, v2, v3 - индексы трех вершин (из теории a, b и с)
- a, b, c - вершины (в векторе храним их координаты)
- p и q - вектора из точки a в b и из a в с соответственно
- n - расчитанная нормаль

Как видите все просто. Для перекрестного произведения векторов p и q с нормализации результата использовались функции D3DXVec3Cross () и D3DXVec3Normalize () .

Еще один аспект. Если оставить все как есть, то освещение получится несколько "ломаным". Что бы избежать этого - необходимо произвести сглаживание нормалей для соседних полигонов. Представьте - вы ведь рассчитывали несколько нормалей для одной точки (для вершин с одинаковыми координатами) но принадлежащими разным полигонам. Я это делаю достаточно просто.

---------------------------------------------

Нельзя вычислить нормаль для вершины, потому что это всего лишь точка в пространстве. Однако можно произвести приблизительный расчет. При понимании идей расчета нормалей для плоскостей и граней, нормали для вершин можно вычислить без особого труда. Нормалью вершины будет являться среднее от нормалей окружающих его граней. Таким образом, определив соседние грани, мы можем легко определить нормаль для данной вершины. Вот примерный алгоритм расчета: создаем переменную n, которая представят собой вектор и инициализируем ее в (0,0,0). Теперь необходимо создать цикл по всем вершинам и для каждого вершины определяем грань, в которую она входит. Если в эту грань так же входит и вершина, для которой мы производим расчет, то нормаль данной грани суммируется с n. Таким образом мы получаем сумму нормалей. Остается только нормализовать n.

---------------------------------------------

Теперь реализация.

В зависимости от входного параметра in_smooth сглаживание производится либо нет. Тут надеюсь все понятно.

Еще немного - у меня объекты могут состоять из нескольких частей. Это предусмотрено и при нормализации это необходимо предусмотреть - вот как выглядит вся функция нормализации у меня в классе :

Вот теперь, пожалуй, все. Пример остался пока тот же, а скриншот я сделал другой.




Комментарии

 Ваш комментарий к данному материалу будет интересен нам и нашим читателям!



Последние статьи: Графика / Direct x /

DirectX
17-05-2010   

Это - библиотека диспетчера Microsoft DirectX, чтобы оптимизировать графы и звуковые представления для Windows... подробнее

Кол. просмотров: общее - 2944 сегодня - 0

Особенности программирования DirectX графики
07-02-2009   

Особенности программирования DirectX графики для видео карт nVidia (по материалам nVidia)... подробнее

Кол. просмотров: общее - 3323 сегодня - 1

DirectX 8.0 FAQ
26-01-2009   
Кол. просмотров: общее - 3731 сегодня - 0

Пишем DirectX-движок
25-01-2009   

Темой этого урока я решил сделать написание т. н. движка. Полагая, что всегда существует определённый контингент людей, только начавших изучать мультимедийные и игровые технологии, и плавающие в загадочных понятиях, объясню, что такое движок и на каком бензине он работает... подробнее

Кол. просмотров: общее - 3349 сегодня - 1

Что может наша видеокарта, что можем сделать мы и как это узнать?
15-01-2009   

По прошествии некоторого времени после празднования Нового Года и всего, что с ним связано, предлагаю вашему вниманию новый урок. Посвящен он будет извлечению информации о возможностях вашей видео карты... подробнее

Кол. просмотров: общее - 3178 сегодня - 1



  WWW.COMPROG.RU - 2009-2012 | Designed and Powered by Zaipov Renat | Projects