netlib.narod.ru< Назад | Оглавление | Далее >

Добавление к миру трехмерных объектов

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

Здесь нам снова потребуется использовать пирамиду видимого пространства для быстрого определения того, какие объекты видимы, а какие нет. Чтобы определить видимость трехмерного объекта вы заключаете его в невидимую сферу, называемую ограничивающей сферой (bounding sphere), которая будет использоваться совместно с функцией CheckSphere класса пирамиды видимого пространства (смотрите раздел «Класс cFrustum» ранее в этой главе).

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


Рис. 8.7. Вы можете проверить три объекта в сцене относительно пирамиды видимого пространства

Рис. 8.7. Вы можете проверить три объекта в сцене относительно пирамиды видимого пространства


На рис. 8.7 только два объекта находятся в пирамиде видимого пространства и видны зрителю. Один объект полностью находится вне пирамиды видимого пространства. Вы захотите иметь возможность рисовать только видимые объекты и пропускать те, которые расположены вне пирамиды. Для этого вы должны вычислить ограничивающую сферу каждого объекта и затем проверить ее, чтобы убедиться, находится ли она внутри пирамиды.

Вычисление ограничивающей сферы

Если вы не используете класс сеток графического ядра, вам необходимо определить ограничивающую сферу сетки. Используя D3DX, вы можете обратиться к функции D3DXComputeBoundingSphere (именно она используется в графическом ядре):

HRESULT D3DXComputeBoundingSphere(
     PVOID       pvPointsFVF, // Буфер, содержащий вершины
     DWORD       NumVertices, // Количество вершин в буфере
     DWORD       FVF,         // Дескриптор FVF
     D3DXVECTOR3 *pCenter,    // &D3DXVECTOR2(0.0f, 0.0f, 0.0f)
     FLOAT       *pRadius);   // Указатель на переменную радиуса

Эта функция просто сканирует буфер вершин, запоминая какая вершина больше всего удалена от центра. Расстояние от центра до этой вершины и является радиусом сферы. Перед вызовом D3DXComputeBoundingSphere вам надо заблокировать буфер вершин с помощью следующего вызова:

HRESULT ID3DXMesh::LockVertexBuffer(
     DWORD Flags,     // Флаги блокировки. Используйте D3DLOCK_READONLY
     BYTE  **ppData); // Указатель на данные буфера вершин

 

ПРИМЕЧАНИЕ
ID3DXMesh и ID3DXSkinMesh используют для блокировки буфера вершин одну и ту же функцию, так что вызов для ID3DXMesh подходит и для ID3DXSkinMesh.

Когда сетка загружена, все готово к вычислению ее ограничивающей сферы, как показано ниже:

// pMesh = ранее загруженный объект ID3DXMesh
float Radius; // Радиус объекта
BYTE  **Ptr;  // Указатель на буфер вершин

// Блокируем буфер вершин
if(SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_READONLY,
                                     (BYTE**)&Ptr))) {

    // Вычисляем радиус ограничивающей сферы
    D3DXComputeBoundingSphere((void*)Ptr,
              pMesh->GetNumVertices(), pMesh->GetFVF(),
              &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &Radius);

    // Разблокируем буфер вершин
    pMesh->UnlockVertexBuffer();
}

Обратите внимание, что в вызове D3DXComputeBoundingSphere количество вершин и дескриптор FVF запрашиваются непосредственно у ID3DXMesh. За вызовом ID3DXMesh::LockVertexBuffer следует вызов ID3DXMesh::UnlockVertexBuffer. Вы должны разблокировать буфер вершин, закончив работу с ним, иначе последующие вызовы блокировки или визуализации буфера приведут к сбою.

Ограничивающие сферы и пирамида видимого пространства

Сейчас, когда у вас сконструирована пирамида видимого пространства и есть ограничивающая сфера, можно вызвать функцию cFrustum::CheckSphere, чтобы проверить видим ли объект:

// cFrustum *Frustum = ранее созданная пирамида видимого пространства
// Radius = ранее вычисленный радиус ограничивающей сферы
// XPos, YPos, ZPos = Мировые координаты объекта
if(Frustum->CheckSphere(XPos, YPos, ZPos, Radius) == TRUE) {

    // Объект внутри пирамиды, переходим к его визуализации

} else {

    // Объект вне пирамиды, пропускаем визуализацию

}

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz