netlib.narod.ru | < Назад | Оглавление | Далее > |
Трехмерный мир не будет завершенным без объектов. Поскольку вы используете трехмерный мир, в качестве игровых объектов хорошо использовать трехмерные сетки; однако, как вы видели в разделе «Сетки в качестве уровней», тупое рисование тысяч объектов (без какого-либо отбрасывания) вызовет существенные задержки в конвейере визуализации графики.
Здесь нам снова потребуется использовать пирамиду видимого пространства для быстрого определения того, какие объекты видимы, а какие нет. Чтобы определить видимость трехмерного объекта вы заключаете его в невидимую сферу, называемую ограничивающей сферой (bounding sphere), которая будет использоваться совместно с функцией CheckSphere класса пирамиды видимого пространства (смотрите раздел «Класс cFrustum» ранее в этой главе).
На рис. 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); // Указатель на данные буфера вершин
Когда сетка загружена, все готово к вычислению ее ограничивающей сферы, как показано ниже:
// 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 | < Назад | Оглавление | Далее > |