DirectX9.0:網格的建立與繪製
本例程演示瞭如何建立一個簡單的立方體網格並進行繪製
主要的流程如下:
- 建立空網格物件
- 將立方體的面片資料寫入網格快取
- 指定網格中每個面片所屬的子集
- 生成該網格的鄰接資訊
- 優化網格
- 繪製網格
總結紅龍書中的例程程式碼如下:
d3dUtility.h
#ifndef __d3dUtilityH__ #define __d3dUtilityH__ #include <d3dx9.h> namespace d3d { //初始化DirectX3D bool InitD3D( HINSTANCE hInstance, // [in] Application instance. int width, int height, // [in] Backbuffer dimensions. bool windowed, // [in] Windowed (true)or full screen (false). D3DDEVTYPE deviceType, // [in] HAL or REF IDirect3DDevice9** device);// [out]The created device. //訊息迴圈 int EnterMsgLoop( bool(*ptr_display)(float timeDelta)); LRESULT CALLBACK Wnd_Proc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); template<class T> void Release(T t) { if (t) { t->Release(); t = 0; } } template<class T> void Delete(T t) { if (t) { delete t; t = 0; } } const D3DXCOLOR WHITE(D3DCOLOR_XRGB(255, 255, 255)); const D3DXCOLOR BLACK(D3DCOLOR_XRGB(0, 0, 0)); const D3DXCOLOR RED(D3DCOLOR_XRGB(255, 0, 0)); const D3DXCOLOR GREEN(D3DCOLOR_XRGB(0, 255, 0)); const D3DXCOLOR BLUE(D3DCOLOR_XRGB(0, 0, 255)); const D3DXCOLOR YELLOW(D3DCOLOR_XRGB(255, 255, 0)); const D3DXCOLOR CYAN(D3DCOLOR_XRGB(0, 255, 255)); const D3DXCOLOR MAGENTA(D3DCOLOR_XRGB(255, 0, 255)); D3DMATERIAL9 InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p); const D3DMATERIAL9 WHITE_MTRL = InitMtrl(WHITE, WHITE, WHITE, BLACK, 2.0f); const D3DMATERIAL9 RED_MTRL = InitMtrl(RED, RED, RED, BLACK, 2.0f); const D3DMATERIAL9 GREEN_MTRL = InitMtrl(GREEN, GREEN, GREEN, BLACK, 2.0f); const D3DMATERIAL9 BLUE_MTRL = InitMtrl(BLUE, BLUE, BLUE, BLACK, 2.0f); const D3DMATERIAL9 YELLOW_MTRL = InitMtrl(YELLOW, YELLOW, YELLOW, BLACK, 2.0f); D3DLIGHT9 InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color); D3DLIGHT9 InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color); D3DLIGHT9 InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color); } #endif
d3dUtility.cpp
#include "d3dUtility.h" //#pragma comment(lib,"d3d9.lib") //#pragma comment(lib,"d3dx9.lib") //#pragma comment(lib,"winmm.lib") bool d3d::InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9** device) { // // Create the main application window. // WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)d3d::Wnd_Proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = "Direct3D9App"; if (!RegisterClass(&wc)) { ::MessageBox(0, "RegisterClass() - FAILED", 0, 0); return false; } HWND hwnd = 0; hwnd = ::CreateWindow( "Direct3D9App", "Direct3D9App", WS_EX_APPWINDOW, 0, 0, width, height, 0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); //HWND CreateWindow( // LPCTSTR lpWindowName, // 視窗標題 // DWORD dwStyle, // 視窗風格 // int x, // 初始 x 座標 // int y, // 初始 y 座標 // int nWidth, // 初始 x 方向尺寸 // int nHeight, // 初始 y 方向尺寸 // HWND hWndParent, // 父視窗控制代碼 // HMENU hMenu, // 視窗選單控制代碼 // HINSTANCE hInstance, // 程式例項控制代碼 // LPVOID lpParam // 建立引數 //); if (!hwnd) { ::MessageBox(0, "CreateWindow() - FAILED", 0, 0); return false; } ::ShowWindow(hwnd, SW_SHOW); ::UpdateWindow(hwnd); // Init D3D: HRESULT hr = 0; //要初始化IDirect3D,首先必須獲取指向介面IDrect3D9的指標。使得一個專門的Direct3D函式可以很容易做到 IDirect3D9* d3d9 = 0; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if (!d3d9) { ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0); return false; } //檢驗圖形卡是否支援該硬體頂點運算 D3DCAPS9 caps; d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps); int vp = 0; if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) //硬體頂點運算 vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; else //軟體頂點運算 vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //填充D3DPRESENT_PARAMETERS結構體 D3DPRESENT_PARAMETERS d3dpp; d3dpp.BackBufferWidth = width; //後臺快取中表面的寬度,單位為畫素 d3dpp.BackBufferHeight = height; //後臺快取中表面的高度,單位為畫素 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; //後臺快取的畫素格式(如32位畫素格式:D3DFMT_A8R8G8B8) d3dpp.BackBufferCount = 1; //所需使用的後臺快取的個數,通常是1,需要一個後臺快取 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; //多重取樣型別 d3dpp.MultiSampleQuality = 0; //多重取樣的質量水平 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //列舉型別指定交換鏈中的快取的頁面設定方式。 d3dpp.hDeviceWindow = hwnd; //與裝置相關的視窗控制代碼。指定了所有進行繪製的應用程式視窗 d3dpp.Windowed = windowed; //視窗模式,為false時表示全屏模式 d3dpp.EnableAutoDepthStencil = true; //為true時,自動建立並維護深度快取或模板快取 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; //深度快取或模板快取的畫素格式 d3dpp.Flags = 0; //附加特性 d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //重新整理頻率 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //一般為立即提交或由Direct3D來選擇提交 // 建立IDrect3Device9介面 hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); //HRESULT CreateDevice( // UINT Adapter, // 希望代表的物理顯示卡 // D3DDEVTYPE DeviceType, // 裝置型別 // HWND hFocusWindow, // 視窗控制代碼,指裝置要繪製的目標視窗 // DWORD BehaviorFlags, // 頂點運算型別 // D3DPRESENT_PARAMETERS *pPresentationParameters, // 完成初始化的D3DPRESENT_PARAMETERS結構體 // IDirect3DDevice9 **ppReturnedDeviceInterface // 返回所建立的裝置 //); if (FAILED(hr)) { // 再次使用16位深度快取嘗試 d3dpp.AutoDepthStencilFormat = D3DFMT_D16; hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if (FAILED(hr)) { d3d9->Release(); ::MessageBox(0, "CreateDevice() - FAILED", 0, 0); return false; } } d3d9->Release(); return true; } //訊息迴圈 int d3d::EnterMsgLoop(bool(*ptr_display)(float timeDelta)) { MSG msg; ::ZeroMemory(&msg, sizeof(MSG)); static float lastTime = (float)timeGetTime(); while (msg.message != WM_QUIT) { if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { float currTime = (float)timeGetTime(); //計算相鄰兩次呼叫ptr_display的時間間隔 float timeDelta = (currTime - lastTime)*0.001f; //呼叫指定display函式 ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; } D3DMATERIAL9 d3d::InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p) { D3DMATERIAL9 mtrl; mtrl.Ambient = a; mtrl.Diffuse = d; mtrl.Specular = s; mtrl.Emissive = e; mtrl.Power = p; return mtrl; } D3DLIGHT9 d3d::InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color) { D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Ambient = *color*0.4f; light.Diffuse = *color; light.Specular = *color*0.6f; light.Direction = *direction; return light; } D3DLIGHT9 d3d::InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color) { D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_POINT; light.Ambient = *color * 0.4f; light.Diffuse = *color; light.Specular = *color * 0.6f; light.Position = *position; light.Range = 1000.0f; light.Falloff = 1.0f; light.Attenuation0 = 1.0f; light.Attenuation1 = 0.0f; light.Attenuation2 = 0.0f; return light; } D3DLIGHT9 d3d::InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color) { D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_SPOT; light.Ambient = *color * 0.4f; light.Diffuse = *color; light.Specular = *color * 0.6f; light.Position = *position; light.Direction = *direction; light.Range = 1000.0f; light.Falloff = 1.0f; light.Attenuation0 = 1.0f; light.Attenuation1 = 0.0f; light.Attenuation2 = 0.0f; light.Theta = 0.5f; light.Phi = 0.7f; return light; }
WinMain.cpp
#include "d3dUtility.h" #include <fstream> #include <vector> using namespace d3d; IDirect3DDevice9* device = 0; int width = 640; int height = 480; ID3DXMesh* mesh = 0; const DWORD NumSubsets = 3; IDirect3DTexture9* tex[3] = {0,0,0}; std::ofstream OutFile; void dumpVertices(std::ofstream& OutFile, ID3DXMesh* mesh); //其他四個將網格資料輸出到檔案中的函式都和dumpVertices相似, //因為程式碼中心不在此類函式,所以不再做實現、說明和使用 //void dumpIndices(std::ofstream& outFile, ID3DXMesh* mesh); //void dumpAttributeBuffer(std::ofstream& outFile, ID3DXMesh* mesh); //void dumpAdjacencyBuffer(std::ofstream& outFile, ID3DXMesh* mesh); //void dumpAtrributeTable(std::ofstream& outFile, ID3DXMesh* mesh); typedef struct Vertex { Vertex() {}; Vertex(float x, float y, float z, float nx, float ny, float nz, float u, float v) :_x(x),_y(y),_z(z),_nx(nx),_ny(ny),_nz(nz),_u(u),_v(v) {} float _x, _y, _z; float _nx, _ny, _nz; float _u, _v; static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; }vertex; bool Setup() { //建立空網格 HRESULT hr=0; hr=D3DXCreateMeshFVF( 12, 24, D3DPOOL_MANAGED, vertex::FVF, device, &mesh ); // HRESULT WINAPI D3DXCreateMeshFVF( //也可用D3DXCreateMesh函式建立 // DWORD NumFaces, //網格具有的面片總數 // DWORD NumVertices, //網格具有的頂點總數 // DWORD options, //建立標記 // DWORD FVF, //靈活頂點格式 // LPDIRECT3DDEVICE9 pDevices, //裝置指標 // [out]LPD3DXMESH* ppMesh //建立的網格物件指標 // ) //填充網格頂點資訊 vertex* v=0; mesh->LockVertexBuffer(0, (void**)&v); //front face v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); v[1] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f); v[2] = Vertex(1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f); v[3] = Vertex(1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f); //back face v[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); v[5] = Vertex(1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f); v[6] = Vertex(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); v[7] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); //left face v[8] = Vertex(-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f); v[9] = Vertex(-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f); v[10] = Vertex(-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f); v[11] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f); //right face v[12] = Vertex(1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); v[13] = Vertex(1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); v[14] = Vertex(1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f); v[15] = Vertex(1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f); //top face v[16] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); v[17] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f); v[18] = Vertex(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f); v[19] = Vertex(1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f); //bottom face v[20] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f); v[21] = Vertex(1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f); v[22] = Vertex(1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f); v[23] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f); mesh->UnlockVertexBuffer(); //填充網格索引資訊 DWORD* i = 0; mesh->LockIndexBuffer(0, (void**)&i); //front face i[0] = 0; i[1] = 1; i[2] = 2; i[3] = 0; i[4] = 2; i[5] = 3; //back face i[6] = 4; i[7] = 5; i[8] = 6; i[9] = 4; i[10] = 6; i[11] = 7; //left face i[12] = 8; i[13] = 9; i[14] = 10; i[15] = 8; i[16] = 10; i[17] = 11; //right face i[18] = 12; i[19] = 13; i[20] = 14; i[21] = 12; i[22] = 14; i[23] = 15; //top face i[24] = 16; i[25] = 17; i[26] = 18; i[27] = 16; i[28] = 18; i[29] = 19; //bottom face i[30] = 20; i[31] = 21; i[32] = 22; i[33] = 20; i[34] = 22; i[35] = 23; mesh->UnlockIndexBuffer(); //指定屬性快取的值,即面片所屬的子集 DWORD* attributeBuffer = 0; mesh->LockAttributeBuffer(0, &attributeBuffer); for (int a = 0; a < 4 ; a++) { attributeBuffer[a] = 0; } for (int b = 4; b < 8; b++) { attributeBuffer[b] = 1; } for (int c = 8; c < 12; c++) { attributeBuffer[c] = 2; } mesh->UnlockAttributeBuffer(); //計算鄰接資訊 std::vector<DWORD> adjacencyBuffer(mesh->GetNumFaces()*3); mesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]); //網格優化 hr = mesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, &adjacencyBuffer[0], 0, 0, 0 ); // HRESULT OptimizeInplace( // DWORD Flags, //優化方案 // const DWORD *pAdjacencyIn, //未經優化的鄰接陣列指標 // DWORD *pAdjacencyOut, //優化後的鄰接資訊 // DWORD *pFaceRemap, //網格面片的重繪資訊 // LPD3DXBUFFER *ppVertexRemap //頂點的重繪資訊 // ); //輸出網格資料到檔案中 OutFile.open("Mesh Dump.txt"); dumpVertices(OutFile, mesh); /*dumpIndices(OutFile, mesh); dumpAttributeTable(OutFile, mesh); dumpAttributeBuffer(OutFile, mesh); dumpAdjacencyBuffer(OutFile, mesh);*/ OutFile.close(); //建立三個紋理 D3DXCreateTextureFromFile( //讀入影象檔案,載入到IDirect3DTexture9物件中 //可以載入的影象格式:BMP、DDS、DIB、JPG、PNG、TGA device, //建立紋理的device "tex1.jpg", //載入的影象檔名 &tex[0]); //建立的紋理 D3DXCreateTextureFromFile( device, "tex2.jpg", &tex[1]); D3DXCreateTextureFromFile( device, "tex3.jpg", &tex[2]); //設定紋理過濾和多級漸進紋理過濾 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); device->SetRenderState(D3DRS_LIGHTING, false); //取景變換 D3DXVECTOR3 pos(0.0f, 0.f, -4.0f); D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH( &V, &pos, &target, &up); device->SetTransform(D3DTS_VIEW, &V); //投影變換 D3DXMATRIX proj; D3DXMatrixPerspectiveLH( &proj, D3DX_PI*0.5f, (float)width / (float)height, 1.0f, 1000.f ); device->SetTransform(D3DTS_PROJECTION, &proj); return true; } //cleanup void cleanup() { //釋放網格和所有紋理 d3d::Release<ID3DXMesh*>(mesh); for (int i = 0; i < NumSubsets; i++) { d3d::Release<IDirect3DTexture9*>(tex[i]); } } //display bool display(float deltaTime) { if (device) { //設定旋轉變換 D3DXMATRIX xRot; D3DXMatrixRotationX(&xRot, D3DX_PI * 0.2f); static float y = 0.0f; D3DXMATRIX yRot; D3DXMatrixRotationY(&yRot, y); y += deltaTime; if (y >= 6.28f) y = 0.0f; D3DXMATRIX World = xRot * yRot; device->SetTransform(D3DTS_WORLD, &World); //清屏 device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0); //HRESULT Clear( // DWORD Count, //pRects陣列中矩形的數目 // const D3DRECT *pRects, //所要執行清除操作的螢幕矩形陣列 // DWORD Flags, //所要清除的表面,包括D3DCLEAR_TARGET(後臺快取), D3DCLEAR_ZBUFFER(Z深度快取), D3DCLEAR_STENCIL(模板平面快取) // D3DCOLOR Color, //指定將繪製目標體設定為何種顏色 // float Z, //設定深度快取,[0,1] // DWORD Stencil //模板快取所要設定的值 //); //開始繪製 device->BeginScene(); for (int i = 0; i < NumSubsets; i++) { device->SetTexture(0, tex[i]); mesh->DrawSubset(i); } device->EndScene(); //提交後臺快取 device->Present(0, 0, 0, 0); } return true; } //Wnd_Proc LRESULT CALLBACK d3d::Wnd_Proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; case WM_KEYDOWN: //按下esc退出 if (wparam == VK_ESCAPE) DestroyWindow(hwnd); } return ::DefWindowProc(hwnd, msg, wparam, lparam); } //WinMain int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show) { if (!InitD3D(inst, width, height, true, D3DDEVTYPE_HAL, &device)) { MessageBox(NULL, "init_d3d()-fail.", 0, MB_OK); return 0; } if (!Setup()) { MessageBox(NULL, "setup_d3d()-fail.", 0, MB_OK); return 0; } d3d::EnterMsgLoop(display); cleanup(); device->Release(); return 0; } //dumpVertices void dumpVertices(std::ofstream& OutFile, ID3DXMesh* mesh) { OutFile << "vertices:"; vertex* v = 0; mesh->LockVertexBuffer(0, (void**)&v); OutFile << "---------" << std::endl; for (int i = 0; i < mesh->GetNumVertices(); i++) //輸出頂點資訊 { OutFile << "vertice [" << i << "] : ("; OutFile << v[i]._x << "," << v[i]._y << "," << v[i]._z << ","; OutFile << v[i]._nx << "," << v[i]._ny << "," << v[i]._nz << ","; OutFile << v[i]._u << "," << v[i]._v << "," << std::endl; } mesh->UnlockVertexBuffer(); OutFile << std::endl << std::endl; } //void dumpIndices(std::ofstream& OutFile, ID3DXMesh* mesh){} //void dumpAttributeBuffer(std::ofstream& OutFile, ID3DXMesh* mesh){} //void dumpAdjacencyBuffer(std::ofstream& OutFile, ID3DXMesh* mesh){} //void dumpAttributeTable(std::ofstream& OutFile, ID3DXMesh* mesh){}
輸出的MeshDump.txt如下:
vertices: --------- vertice [0] : (-1,-1,1,0,0,1,0,0) vertice [1] : (1,1,1,0,0,1,1,1) vertice [2] : (-1,1,1,0,0,1,1,0) vertice [3] : (1,-1,1,0,0,1,0,1) vertice [4] : (-1,-1,-1,0,0,-1,0,0) vertice [5] : (1,1,-1,0,0,-1,1,1) vertice [6] : (1,-1,-1,0,0,-1,1,0) vertice [7] : (-1,1,-1,0,0,-1,0,1) vertice [8] : (1,-1,-1,1,0,0,0,0) vertice [9] : (1,1,1,1,0,0,1,1) vertice [10] : (1,-1,1,1,0,0,1,0) vertice [11] : (1,1,-1,1,0,0,0,1) vertice [12] : (-1,-1,1,-1,0,0,0,0) vertice [13] : (-1,1,-1,-1,0,0,1,1) vertice [14] : (-1,-1,-1,-1,0,0,1,0) vertice [15] : (-1,1,1,-1,0,0,0,1) vertice [16] : (-1,-1,-1,0,-1,0,0,0) vertice [17] : (1,-1,1,0,-1,0,1,1) vertice [18] : (-1,-1,1,0,-1,0,1,0) vertice [19] : (1,-1,-1,0,-1,0,0,1) vertice [20] : (-1,1,-1,0,1,0,0,0) vertice [21] : (1,1,1,0,1,0,1,1) vertice [22] : (1,1,-1,0,1,0,1,0) vertice [23] : (-1,1,1,0,1,0,0,1)