我们看到3d世界的奇妙,丰富的场景,真实的物体… … 在DX中是如何实现这样丰富的场景的,一种方法是用DX绘制(用顶点缓存一个一个绘制,如DrawTrangle,DrawTube等),但这样会很麻烦,你要考虑无限物体的参数,考虑它们的位置等;另外一种方法就是在3d制作软件(如3dmax或者maya)中随心所欲地创作好你的3d世界,然后导出为DX可识别的格式(如3dmax导出为XFile),进而在DX中加载进去即可。下面就是整个从3dmax中建好模到用DX显示出来的过程。
1: #include <windows.h>
2: #include <d3dx9.h>
3: #include <vector>
4: using namespace std;
5: HINSTANCE hInstance;
6: IDirect3DDevice9 *Device = 0;
7: const D3DXCOLOR WHITE( D3DCOLOR_XRGB(255, 255, 255) );
8: //设置全局变量,一个ID3DXMesh对象存储从XFile中加载的网格数据,另外两个变量分别存储该网格的材质和纹理数据
9: ID3DXMesh *Mesh = 0;
10: vector<D3DMATERIAL9>Mtrls(0);
11: vector<IDirect3DTexture9*>Textures(0);
12: bool Setup()
13: {
14: //导入XFile数据
15: ID3DXBuffer* adjBuffer = 0;
16: ID3DXBuffer* mtrlBuffer = 0;
17: DWORD numMtrls = 0;
18: D3DXLoadMeshFromX("bigship1.x", D3DXMESH_MANAGED, Device, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &Mesh);
19: //加载XFile文件后,我们必须遍历D3DXMATRIAL数组中的元素,并加载该网格所引用的纹理数据
20: if(mtrlBuffer!=0 && numMtrls!=0)
21: {
22: D3DXMATERIAL *mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
23: for(int i=0; i<numMtrls; i++)
24: {
25: //设置MatD3D的属性
26: mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;
27: //保存第i个材质
28: Mtrls.push_back(mtrls[i].MatD3D);
29: //检查第i个材质是否有纹理
30: if(mtrls[i].pTextureFilename != 0)
31: {
32: //是的话导入纹理信息
33: IDirect3DTexture9* tex = 0;
34: D3DXCreateTextureFromFile(Device, mtrls[i].pTextureFilename, &tex);
35: //保存导入的纹理
36: Textures.push_back(tex);
37: }
38: else
39: {
40: //不是的话
41: Textures.push_back(0);
42: }
43: }
44: }
45: Mesh->OptimizeInplace(
46: D3DXMESHOPT_ATTRSORT |
47: D3DXMESHOPT_COMPACT |
48: D3DXMESHOPT_VERTEXCACHE,
49: (DWORD*)adjBuffer->GetBufferPointer(),
50: 0, 0, 0);
51: //
52: // Set texture filters.
53: //
54: Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
55: Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
56: Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
57: //
58: // Set Lights.
59: //
60: D3DLIGHT9 dir;
61: ZeroMemory(&dir, sizeof(dir));
62: dir.Type = D3DLIGHT_DIRECTIONAL;
63: dir.Diffuse = WHITE;
64: dir.Specular = WHITE * 0.3f;
65: dir.Ambient = WHITE * 0.6f;
66: dir.Direction = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
67: //
68: // Set and Enable the light.
69: //
70: Device->SetLight(0, &dir);
71: Device->LightEnable(0, true);
72: //
73: // Set camera.
74: //
75: D3DXVECTOR3 pos(4.0f, 4.0f, -13.0f);
76: D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
77: D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
78: D3DXMATRIX V;
79: D3DXMatrixLookAtLH(
80: &V,
81: &pos,
82: &target,
83: &up);
84: Device->SetTransform(D3DTS_VIEW, &V);
85: //
86: // Set projection matrix.
87: //
88: D3DXMATRIX proj;
89: D3DXMatrixPerspectiveFovLH(
90: &proj,
91: D3DX_PI * 0.5f, // 90 - degree
92: 800.0f/600.0f,
93: 1.0f,
94: 1000.0f);
95: Device->SetTransform(D3DTS_PROJECTION, &proj);
96: return true;
97: }
98: void Cleanup()
99: {
100: }
101: void Display(float time)
102: {
103: if(Device)
104: {
105: static float y = 0.0f;
106: D3DXMATRIX yRot;
107: D3DXMatrixRotationY(&yRot, y);
108: y = y + time;
109: if(y>6.28f)
110: y = 0.0f;
111: D3DXMATRIX World = yRot;
112: Device ->SetTransform(D3DTS_WORLD, &World);
113: Device ->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x0000ffff, 1.0f, 0);
114: Device ->BeginScene();
115: for(int i=0; i<Mtrls.size(); i++)
116: {
117: Device ->SetMaterial(&Mtrls[i]);
118: Device ->SetTexture(0, Textures[i]);
119: Mesh ->DrawSubset(i);
120: }
121: Device ->EndScene();
122: Device ->Present(0, 0, 0, 0);
123: }
124: }
125: LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
126: {
127: switch(uMsg)
128: {
129: case WM_DESTROY:
130: PostQuitMessage(0);
131: break;
132: case WM_KEYDOWN:
133: if( wParam == VK_ESCAPE )
134: DestroyWindow(hWnd);
135: break;
136: default:
137: return DefWindowProc(hWnd, uMsg, wParam, lParam);
138: }
139: return 0;
140: }
141: int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
142: {
143: MSG msg;
144: ZeroMemory(&msg, sizeof(msg));
145: WNDCLASSEX wc;
146: wc.cbClsExtra = NULL;
147: wc.cbSize = sizeof(wc);
148: wc.cbWndExtra = NULL;
149: wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
150: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
151: wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
152: wc.hIconSm = NULL;
153: wc.hInstance = hInstance;
154: wc.lpfnWndProc = WndProc;
155: wc.lpszClassName = "draw";
156: wc.lpszMenuName = NULL;
157: wc.style = CS_DROPSHADOW;
158: RegisterClassEx(&wc);
159: HWND hWnd = CreateWindowEx(WS_EX_COMPOSITED, "draw", "draw", WS_HSCROLL, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);
160: ShowWindow(hWnd, SW_NORMAL);
161: UpdateWindow(hWnd);
162: IDirect3D9 *D3D9 = 0;
163: D3D9 = Direct3DCreate9(D3D_SDK_VERSION);
164: D3DCAPS9 caps;
165: D3D9 ->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
166: int vp = 0;
167: if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
168: vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
169: else
170: vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
171: D3DPRESENT_PARAMETERS d3dpp;
172: d3dpp.BackBufferWidth = 800;
173: d3dpp.BackBufferHeight = 600;
174: d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
175: d3dpp.BackBufferCount = 1;
176: d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
177: d3dpp.MultiSampleQuality = 0;
178: d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
179: d3dpp.hDeviceWindow = hWnd;
180: d3dpp.Windowed = true;
181: d3dpp.EnableAutoDepthStencil = true;
182: d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
183: d3dpp.Flags = 0;
184: d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
185: d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
186: HRESULT hr = D3D9-> CreateDevice(
187: D3DADAPTER_DEFAULT,
188: D3DDEVTYPE_HAL,
189: hWnd,
190: vp,
191: &d3dpp,
192: &Device);
193: while(msg.message != WM_QUIT)
194: {
195: if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
196: {
197: TranslateMessage(&msg);
198: DispatchMessage(&msg);
199: }
200: else
201: {
202: Setup();
203: Display(0.016f);
204: }
205: }
206: return 0;
207: }