Помощь по DirectX 9.
AlexsSyr Дата: Четверг, 13 Ноября 2014, 19:54 | Сообщение # 1
почетный гость
Сейчас нет на сайте
Решил поработать с DirectX 9. Получилось вывести модель на экран. Тут же попробовал вывести две разных модели так:
Код
//----------------------------------------------------------------------------------- // Mesh.CPP // Загружаем Х файл //----------------------------------------------------------------------------------- #include <windows.h> // Подключаем заголовочный файл Windows #include <d3d9.h> // Подключаем заголовочный файл DirectX 9 SDK #include <d3dx9.h> // Подключаем из D3DX утилит для работы с матрицами #include <mmsystem.h> // Подключаем системную библеотеку #include <d3dx9core.h> // Подключаем системный заголовочный файл #include <d3dx9mesh.h> // Подключаем заголовочный файл для работы с меш #include<string> #include<iostream> #include<fstream> using namespace std; //----------------------------------------------------------------------------------- // Глобальные переменные //----------------------------------------------------------------------------------- LPDIRECT3D9 pDirect3D = NULL; // Главный Direct3D обьект LPDIRECT3DDEVICE9 pDirect3DDevice = NULL; // Устройство LPD3DXMESH pMesh; LPD3DXBUFFER pMeshBuffer; D3DMATERIAL9* pMeshMaterials; LPDIRECT3DTEXTURE9* pMeshTextura; DWORD dwNumber; DWORD dwNumberArray[10000]; LPDIRECT3DTEXTURE9* pMeshTexturaArray[10000]; D3DMATERIAL9* pMeshMaterialsArray[10000]; LPD3DXMESH pMeshArray[10000]; boolean start = false; int objectCount; FLOAT CamX; FLOAT CamY; FLOAT CamZ; FLOAT X[10000]; FLOAT Y[10000]; FLOAT Z[10000]; FLOAT Xr[10000]; FLOAT Yr[10000]; FLOAT Zr[10000]; string ObjectList[10000]; //----------------------------------------------------------------------------------- // Функция // InitialDirect3D() // Инициализация Direct3D //----------------------------------------------------------------------------------- HRESULT InitialDirect3D( HWND hwnd ) { if( NULL == ( pDirect3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; D3DDISPLAYMODE Display; if( FAILED( pDirect3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &Display ) ) ) return E_FAIL; D3DPRESENT_PARAMETERS Direct3DParametr; ZeroMemory( &Direct3DParametr, sizeof(Direct3DParametr) ); Direct3DParametr.Windowed = FALSE; Direct3DParametr.SwapEffect = D3DSWAPEFFECT_DISCARD; Direct3DParametr.BackBufferFormat = Display.Format; Direct3DParametr.EnableAutoDepthStencil = TRUE; Direct3DParametr.AutoDepthStencilFormat = D3DFMT_D16; Direct3DParametr.BackBufferWidth = GetSystemMetrics(SM_CXSCREEN); Direct3DParametr.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN); Direct3DParametr.BackBufferCount = 3; Direct3DParametr.FullScreen_RefreshRateInHz = Display.RefreshRate; if( FAILED( pDirect3D -> CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &Direct3DParametr, &pDirect3DDevice ) ) ) return E_FAIL; pDirect3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); pDirect3DDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff ); // Подключаем Z буфер pDirect3DDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_TRUE); return S_OK; } //----------------------------------------------------------------------------------- // Функция // InitialMesh() // Инициализация Меша //----------------------------------------------------------------------------------- HRESULT InitialMesh(string ModelName) { if (FAILED(D3DXLoadMeshFromX(ModelName.c_str(), D3DXMESH_SYSTEMMEM, pDirect3DDevice, NULL, &pMeshBuffer, NULL, &dwNumber, &pMesh))) return E_FAIL; // Мы должны извлечь материальные свойства и названия{имена} структуры от // pD3DXMtrlBuffer D3DXMATERIAL* D3DXMeshMaterials = (D3DXMATERIAL *)pMeshBuffer->GetBufferPointer(); pMeshMaterials = new D3DMATERIAL9[dwNumber]; pMeshTextura = new LPDIRECT3DTEXTURE9[dwNumber]; for( DWORD i=0; i<dwNumber; i++ ) { // Копируем материал pMeshMaterials[i] = D3DXMeshMaterials[i].MatD3D; // Установить окружающего свет pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse; // Загружаем текстуру if( FAILED( D3DXCreateTextureFromFile( pDirect3DDevice, D3DXMeshMaterials[i].pTextureFilename, &pMeshTextura[i] ) ) ) pMeshTextura[i]=NULL; } // Уничтожаем материальный буфер pMeshBuffer->Release(); return S_OK; } //Загрузка void LoadLevel(string LevelName){ string buffer; freopen(LevelName.c_str(), "r", stdin); cin >> buffer; CamX = stof(buffer); cin >> buffer; CamY = stof(buffer); cin >> buffer; CamZ = stof(buffer); cin >> objectCount; for (int i = 0; i < objectCount; i++){ cin >> ObjectList[i]; cin >> buffer; X[i] = stof(buffer); cin >> buffer; Y[i] = stof(buffer); cin >> buffer; Z[i] = stof(buffer); cin >> buffer; Xr[i] = stof(buffer); cin >> buffer; Yr[i] = stof(buffer); cin >> buffer; Zr[i] = stof(buffer); } } //------------------------------------------------------------------------- // Функция // DrawMyMesh() // Рисует созданный объект //-------------------------------------------------------------------------- VOID DrawMyMesh() { for( DWORD i=0; i<dwNumber; i++ ) { // Устанавливаем материал и текстуру pDirect3DDevice->SetMaterial( &pMeshMaterials[i] ); pDirect3DDevice->SetTexture(0, pMeshTextura[i]); // Рисуем Меш pMesh->DrawSubset( i ); } } //----------------------------------------------------------------------------- // Функция // Matrix() // Мировая матрица, матрица вида, матрица проекции //----------------------------------------------------------------------------- VOID Matrix() { D3DXMATRIX MatrixWorld, MatrixWorldX, MatrixWorldY; // Мировая матрица (MatrixWorld) D3DXMATRIX MatrixView; // Матрица вида (MatrixView) D3DXMATRIX MatrixProjection; // Матрица проекции (MatrixProjection) // MatrixWorld UINT Time = timeGetTime() % 5000; FLOAT Angel = Time * (2.0f * D3DX_PI) / 5000.0f; D3DXMatrixRotationY( &MatrixWorldY, Angel ); pDirect3DDevice->SetTransform( D3DTS_WORLD,&MatrixWorldY ); // MatrixView D3DXMatrixLookAtLH( &MatrixView, &D3DXVECTOR3 ( CamX, CamY,CamZ ), &D3DXVECTOR3 ( 0.0f, 0.0f, 0.0f ), &D3DXVECTOR3 ( 0.0f, 1.0f, 0.0f ) ); pDirect3DDevice->SetTransform( D3DTS_VIEW, &MatrixView ); // MatrixProjection D3DXMatrixPerspectiveFovLH( &MatrixProjection, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); pDirect3DDevice->SetTransform( D3DTS_PROJECTION, &MatrixProjection ); } //----------------------------------------------------------------------------------- // Функция // RenderingDirect3D() // Рисуем //----------------------------------------------------------------------------------- VOID RenderingDirect3D() { if(pDirect3DDevice == NULL) // Проверяем ошибки return; // Чистим задний буфер pDirect3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(60,100,150), 1.0f, 0 ); // Начало сцены, здесь происходит прорисовка сцены pDirect3DDevice->BeginScene(); for (int i = 0; i < objectCount;i++){ InitialMesh(ObjectList[i]); // Матрицы Matrix(); // Рисуем Меш DrawMyMesh(); } // Конец сцены pDirect3DDevice->EndScene(); // Выводим на экран pDirect3DDevice->Present( NULL, NULL, NULL, NULL ); } //----------------------------------------------------------------------------------- // Функция // DeleteDirect3D() // Освобождает захваченные ресурсы //----------------------------------------------------------------------------------- VOID DeleteDirect3D() { if( pMeshMaterials != NULL ) delete[] pMeshMaterials; if( pMeshTextura ) { for( DWORD i = 0; i < dwNumber; i++ ) { if( pMeshTextura[i] ) pMeshTextura[i]->Release(); } delete[] pMeshTextura; } if( pMesh != NULL ) pMesh->Release(); if( pDirect3DDevice != NULL) pDirect3DDevice->Release(); if( pDirect3D != NULL) pDirect3D->Release(); } //----------------------------------------------------------------------------------- // Функция // MainWinProc() // Здесь происходит обработка сообщений //----------------------------------------------------------------------------------- LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch(msg) { case WM_DESTROY: { DeleteDirect3D(); PostQuitMessage(0); return(0); } case WM_KEYDOWN: { if(wparam==VK_ESCAPE) PostQuitMessage(0); return 0; } } return DefWindowProc(hwnd, msg, wparam, lparam); } //----------------------------------------------------------------------------------- // Функция // WinMain // Входная точка приложения //----------------------------------------------------------------------------------- int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { WNDCLASSEX windowsclass; // Создаем класс HWND hwnd; // Создаем дескриптор окна MSG msg; // Идентификатор сообщения // Определим класс окна WNDCLASSEX windowsclass.cbSize = sizeof(WNDCLASSEX); windowsclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; windowsclass.lpfnWndProc = MainWinProc; windowsclass.cbClsExtra = 0; windowsclass.cbWndExtra = 0; windowsclass.hInstance = hinstance; windowsclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); windowsclass.hCursor = LoadCursor(NULL, IDC_ARROW); windowsclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); windowsclass.lpszMenuName = NULL; windowsclass.lpszClassName = "WINDOWSCLASS"; windowsclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Зарегистрируем класс if (!RegisterClassEx(&windowsclass)) return(0); // Теперь когда класс зарегестрирован можно создать окно if (!(hwnd = CreateWindowEx(NULL, // стиль окна "WINDOWSCLASS", // класс 0, // название окна WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0,0, // левый верхний угол GetSystemMetrics(SM_CXSCREEN),// ширина GetSystemMetrics(SM_CYSCREEN),// высота NULL, // дескриптор родительского окна NULL, // дескриптор меню hinstance, // дескриптор экземпляра приложения NULL))) // указатель на данные окна return 0; if( SUCCEEDED( InitialDirect3D( hwnd ) ) ) { ShowWindow( hwnd, SW_SHOWDEFAULT ); UpdateWindow( hwnd ); ZeroMemory( &msg, sizeof(msg)); while( msg.message!=WM_QUIT) { if(PeekMessage( &msg, NULL,0,0,PM_REMOVE )) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else if (start == false){ start = true; LoadLevel("Main.lvl"); } RenderingDirect3D(); } } return 0; }
Получилось. Только прога есть более 1Гб оперативки. Как я понял проблема в InitialMesh(). Его нужно вызывать 1 раз, но так ничего не работает. Помогите решить проблему. Заранее спасибо.
Archido Дата: Четверг, 13 Ноября 2014, 23:10 | Сообщение # 2
Сэнсэй
Сейчас нет на сайте
Цитата AlexsSyr (
)
Как я понял проблема в InitialMesh(). Его нужно вызывать 1 раз, но так ничего не работает.
Да, дело в этом. А не работает потому, что ты пытаешься использовать одни и те же переменные (pMesh, pMeshMaterials, etc) для разных моделей, т.е. рисоваться всегда будет то, что загрузилось в последнем InitialMesh(). По-хорошему надо создать стуктурку, поместив туда pMesh, pMeshMaterials, текстуры, кол-во сабсетов и т.п., и вот эту структурку уже заполнять в InitialMesh для каждой уникальной модели.
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
AlexsSyr Дата: Пятница, 14 Ноября 2014, 07:18 | Сообщение # 3
почетный гость
Сейчас нет на сайте
Спасибо, разобрался. А не мог бы подсказать как сделать pointligth.
Archido Дата: Пятница, 14 Ноября 2014, 14:30 | Сообщение # 4
Сэнсэй
Сейчас нет на сайте
Цитата AlexsSyr (
)
А не мог бы подсказать как сделать pointligth.
Если ты про стандартное освещение в DX - то без понятия. И оно уже старо как мир, нормальное освещение уже довольно давно делается через шейдеры.
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
Saitei Дата: Пятница, 14 Ноября 2014, 18:47 | Сообщение # 5
старожил
Сейчас нет на сайте
Цитата AlexsSyr (
)
А не мог бы подсказать как сделать pointligth.
Цитата Archido (
)
Если ты про стандартное освещение в DX - то без понятия. И оно уже старо как мир, нормальное освещение уже довольно давно делается через шейдеры.
Угу. Копай в сторону deffered shading
Archido Дата: Пятница, 14 Ноября 2014, 20:30 | Сообщение # 6
Сэнсэй
Сейчас нет на сайте
Цитата Saitei (
)
Копай в сторону deffered shading
ну и зачем? Это уже ненужный перебор. Обычный Forward, классический и простой Ламберт (+Фонг, для бликов) для diffuse - и можно сделать простой pointlight.
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)