« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга



ПнВтСрЧтПтСбВс
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
    Популярное
Функция AccessResource

Определение праздничных дней в табеле

Заместители и заглушки

Функция CreateIcon

Итераторы библиотеки STL

Создание news-reader'а с веб-интерфейсом.

Функция CreateCompatibleBitmap

Разработка собственных листов рассылки

Типы значений

Запросы к базам данных ClearQuest Oracle 10g




    Архив файлов



    Сообщества

    Документация

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 185
Пользователей: 1
  • KRoman

  • Статьи:: Графика и игроделание DirectX, OpenGL etc.) :: Direct3D :: Техника индексирования вершин примитивов



    отправить ссылку другу версия для печати  Обсудить на форуме

    Техника индексирования вершин примитивов



    Приветствую всех, кому предназначены данные уроки. В данном уроке мы рассмотрим один, весьма важный и полезный аспект - индексация примитивов (полигонов). Что это такое? Данный прием позволяет нам избежать повторения данных при задании вершин. Допустим, у вас есть куб - для его задания нам достаточно восемь вершин (в реальном мире), а при наших знаниях на данный момент - для его задания в нашей программе нам понадобится задавать двадцать четыре точки (на одну грань по два полигона, каждый полигон из трех вершин - 2*6*2=24). Если нам понадобится изменить какие-нибудь атрибуты конкретной вершины то, в первом случае мы изменяем параметры всего одной точки, во втором же нам придется изменять параметры от трех до шести заданных нами псевдовершин:

    Тут нам поможет индексирование полигонов. Мы просто создаем нужные нам вершины и потом задаем полигоны путем указания необходимых индексов (каждый из которых сопоставляется вершине). Это позволяет нам избавиться от многократного повторения одних и тех же данных (что в свою очередь позволяет нам экономить память), а также от проблемы обновления этих же данных (также как и Скорости их обновления), но в некоторых случаях мы теряем один аспект - координаты текстур - так как для каждой текстуры мы задаем их только одиножды, а в случае с кубом, если нам надо на каждую грань "натянуть" по текстуре, то нам просто необходимо будет задавать несколько вершин - для каждой грани свои.

    Итак, с небольшой теорией покончено, теперь возьмемся за практическое применение. С индексными буферами мы уже сталкивались в предыдущем уроке, так что я кое в чем немного повторюсь. Как обычно, сперва зададим необходимые переменные и интерфейсы:

    
    LPDIRECT3DVERTEXBUFFER8 p_VertexBuffer = NULL; // our VertexBuffer
    LPDIRECT3DINDEXBUFFER8  p_IndexBuffer  = NULL; // our IndexBuffer
    
    

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

    
    WORD *FlagIndices;
    CUSTOMVERTEX *FlagVertices;
    #define FLAG_SIZE         50
    #define NUM_FLAG_VERTICES ((FLAG_SIZE+1)*(FLAG_SIZE+1))
    #define NUM_FLAG_INDICES  (FLAG_SIZE*FLAG_SIZE*6)
    
    

    --- два массива - один для заполнения его данными о вершинах, другой для представления индексов.
    --- далее идут три переменные - размер стороны квадрата; число вершин, необходимых для создания нашей поверхности заданного размера; и количество индексов, представляющих нашу поверхность.

    Собственно теперь мы можем создавать необходимые нам данные. Для начала создадим массив вершин и создадим по ним вертексный буфер:

    
    FlagVertices = new CUSTOMVERTEX [NUM_FLAG_VERTICES];
    for(ix=0; ix<FLAG_SIZE+1; ix++)
    for(WORD iy=0; iy>FLAG_SIZE+1; iy++)
    {
    	FLOAT tu = ix/(float)FLAG_SIZE;
    	FLOAT tv = iy/(float)FLAG_SIZE;
    
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].x = (float)(ix - FLAG_SIZE/2);
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].y = 
    		3.0f*(cos((float)iy/3.0f)+cos((float)ix/3.0f));
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].z = (float)(iy - FLAG_SIZE/2);
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].nx = 0.0f;
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].ny = 1.0f;
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].nz = 0.0f;
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].tu = (float)(tu*4);
    	FlagVertices[ix+iy*(FLAG_SIZE+1)].tv = (float)(tv*4);
    };
    
    p_d3d_Device->CreateVertexBuffer (NUM_FLAG_VERTICES*sizeof(CUSTOMVERTEX), 
    		0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED, &p_VertexBuffer);
    
    VOID* pVertices;
    p_VertexBuffer->Lock (0, NUM_FLAG_VERTICES*sizeof(CUSTOMVERTEX), 
    		(BYTE**)&pVertices, 0);
    memcpy (pVertices, FlagVertices, NUM_FLAG_VERTICES*sizeof(CUSTOMVERTEX));
    p_VertexBuffer->Unlock();
    
    

    Собственно, тут ничего нового нет, мы просто создаем массив необходимых данных, затем создаем вертексный буфер ( CreateVertexBuffer() ), и следующим шагом копируем наши данные в созданный буфер.

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

    
    FlagIndices = new WORD [NUM_FLAG_INDICES];
    	
    for(WORD i=0, ix=0; ix<LAG_SIZE; iy++ )
    {
    	FlagIndices[i++] = (ix+0) + (iy+1)*(FLAG_SIZE+1);
    	FlagIndices[i++] = (ix+0) + (iy+0)*(FLAG_SIZE+1);
    	FlagIndices[i++] = (ix+1) + (iy+0)*(FLAG_SIZE+1);
    	FlagIndices[i++] = (ix+0) + (iy+1)*(FLAG_SIZE+1);
    	FlagIndices[i++] = (ix+1) + (iy+0)*(FLAG_SIZE+1);
    	FlagIndices[i++] = (ix+1) + (iy+1)*(FLAG_SIZE+1);
    };
    
    p_d3d_Device->CreateIndexBuffer (NUM_FLAG_INDICES*sizeof(WORD), 
    		0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &p_IndexBuffer);
    
    VOID* pVerticesI;
    p_IndexBuffer->Lock (0, NUM_FLAG_INDICES*sizeof(WORD), (BYTE**)&pVerticesI, 0);
    memcpy (pVerticesI, FlagIndices, NUM_FLAG_INDICES*sizeof(WORD));
    p_IndexBuffer->Unlock();
    
    

    вот теперь, после того как мы все это проинициализировали, мы можем заняться рендерингом. Вот выдержки из функции рендеринга окна:

    
    p_d3d_Device->BeginScene ();
    
    p_d3d_Device->SetVertexShader (D3DFVF_CUSTOMVERTEX);
    p_d3d_Device->SetStreamSource (0, p_VertexBuffer, sizeof(CUSTOMVERTEX));
    p_d3d_Device->SetIndices (p_IndexBuffer, 0);
    
    p_d3d_Device->SetMaterial (&mtrl0);
    p_d3d_Device->SetTexture (0, textura001);
    p_d3d_Device->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    p_d3d_Device->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
    p_d3d_Device->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE);
    p_d3d_Device->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 
    		NUM_FLAG_VERTICES, 0, NUM_FLAG_INDICES/3); 
    
    p_d3d_Device->EndScene ();
    
    

    похожий кусок кода вы уже встречали в предыдущем уроке, и тут надеюсь все понятно.

    Теперь при запуске получившегося кода вы должны увидеть нечто похожее на это:

    И не забудьте после использования все за собой убрать :)

    
    _DELETE_ (FlagIndices);
    _DELETE_ (FlagVertices);
    _RELEASE_ (p_VertexBuffer);
    _RELEASE_ (p_IndexBuffer);
    
    

    P.S. Для данного и некоторых последующих уроков, я вел в программу небольшую обработку ввода с клавиатуры (в оконной функции):

    
    case WM_KEYDOWN:
    {
    	if(wParam==VK_NEXT)
    		p_d3d_Device->SetRenderState (D3DRS_FILLMODE, D3DFILL_WIREFRAME);
    	if(wParam==VK_PRIOR)
    		p_d3d_Device->SetRenderState (D3DRS_FILLMODE, D3DFILL_SOLID);
    
    	if(wParam==VK_ADD) distance--;
    	if(wParam==VK_SUBTRACT) distance++;
    ....
    
    
    

    --- нажав на PAGE_UP/PAGE_DOWN , мы меняем режим отображения - полигонами/каркасной сеткой.
    --- на цифровой клавиатуре +/- , позволят нам менять расстояние до центра.

    за более полной информацией смотрите исходный код примера для данного урока.




    Рубрика: Direct3D

    {BLOCK|article|lastarticle||non.tpl}

    Цитата дня (все,добавить):

    Портал фрилансеров

    работа на дому


        Рубрикатор

    Программирование

    C/С++
    Обучение
    Windows API
    XAML
    Моделирование
    Паттерны
    Visual Basic 7 .NET
    WxWidgets
    Функции WinApi
    Функции С++
    Разработка под Mac OS
    Eiffel
    Visual Studio 2008
    UI дизайн
    Алгоритмы
    Конкурсные статьи
    Turbo Pascal
    Visual Studio
    CASE-средства
    Visual Studio 2005
    Без VCL
    Delphi
    Тех. документация
    Тестирование
    Software Testing
    ООП
    TCP/IP
    Google Android
    Windows Installer
    .NET Framework
    Драйвера
    C# C Sharp
    Справка
    Проектирование
    Информ. системы
    Visual Basic
    Assembler
    Оптимизация кода
    Gtk+
    Компоненты
    Реинжиниринг
    Управление проектами
    Extreeme programming
    Lotus Notes
    Алгебраическое проектирование


    Интернет технологии

    PHP
    Perl
    ASP
    WAP
    Cookies
    SSI
    CGI
    Web Servers
    VB Script
    DNS
    CSS
    XML
    Html
    Java Script
    Java2ME
    Firewall
    Flash
    .htaccess
    Apache
    VRML
    Протоколы
    Поисковые системы
    Технология JAVA
    Учебник по PHP
    Учебник по JavaScript
    Учебник по XML
    Java Q&A
    AJAX
    DHTML
    XHTML
    Dreamweaver
    Web 2.0
    Python
    Вебмастеру
    Cisco
    Ruby on Rails
    Silverlight

    Базы данных

    Access
    InterBase
    MySQL
    Oracle
    ADO .NET
    Основы SQL
    Учебник по Access 2002
    MS
    Microsoft FoxPro
    Доступ к данным
    XML в MS SQL Server 2000
    ODBC и MyODBC
    Обучение
    Caché
    DB2
    PostgresSQL
    Sybase
    Теория
    Хранилища данных
    Безопасность
    Реляционные данные
    MySQL и mSQL

    Остальное:

    Разное
    Обзоры книг
    Безопасность
    Графика и дизайн
    Юмор
    Linux
    Фракталы
    Microsoft Axapta
    Многоядерность
    Сети
    Microsoft Office
    Работа
    MS-DOS
    Криптография
    Графика и игроделание
    Новости SDK
    Системы защиты
    Учебник по AutoCad
    CVS
    Windows XP
    Windows Server 2003
    Windows Vista
    Windows 7
    Мероприятия