]> icculus.org git repositories - btb/d2x.git/blob - arch/win32/d3dframe/d3dutil.cpp
Allow use of 22K sound samples
[btb/d2x.git] / arch / win32 / d3dframe / d3dutil.cpp
1 //-----------------------------------------------------------------------------
2 // File: D3DUtil.cpp
3 //
4 // Desc: Shortcut macros and functions for using DX objects
5 //
6 //
7 // Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved
8 //-----------------------------------------------------------------------------
9
10 #define D3D_OVERLOADS
11 #include <math.h>
12 #include <stdio.h>
13 #include "D3DUtil.h"
14
15
16
17 //-----------------------------------------------------------------------------
18 // Name: D3DUtil_InitDeviceDesc()
19 // Desc: Helper function called to initialize a D3DDEVICEDESC structure,
20 //-----------------------------------------------------------------------------
21 VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC& ddDevDesc )
22 {
23     ZeroMemory( &ddDevDesc, sizeof(D3DDEVICEDESC) );
24     ddDevDesc.dwSize                  = sizeof(D3DDEVICEDESC);
25     ddDevDesc.dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
26     ddDevDesc.dlcLightingCaps.dwSize  = sizeof(D3DLIGHTINGCAPS);
27     ddDevDesc.dpcLineCaps.dwSize      = sizeof(D3DPRIMCAPS);
28     ddDevDesc.dpcTriCaps.dwSize       = sizeof(D3DPRIMCAPS);
29 }
30
31
32
33
34 //-----------------------------------------------------------------------------
35 // Name: D3DUtil_InitSurfaceDesc()
36 // Desc: Helper function called to build a DDSURFACEDESC2 structure,
37 //       typically before calling CreateSurface() or GetSurfaceDesc()
38 //-----------------------------------------------------------------------------
39 VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
40                               DWORD dwCaps )
41 {
42     ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
43     ddsd.dwSize                 = sizeof(DDSURFACEDESC2);
44     ddsd.dwFlags                = dwFlags;
45     ddsd.ddsCaps.dwCaps         = dwCaps;
46     ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
47 }
48
49
50
51
52 //-----------------------------------------------------------------------------
53 // Name: D3DUtil_InitViewport()
54 // Desc: Helper function called to build a D3DVIEWPORT3 structure
55 //-----------------------------------------------------------------------------
56 VOID D3DUtil_InitViewport( D3DVIEWPORT2& vp, DWORD dwWidth, DWORD dwHeight )
57 {
58     ZeroMemory( &vp, sizeof(D3DVIEWPORT2) );
59     vp.dwSize   = sizeof(D3DVIEWPORT2);
60     vp.dwWidth  = dwWidth;
61     vp.dwHeight = dwHeight;
62     vp.dvMaxZ   = 1.0f;
63
64     vp.dvClipX      = -1.0f;
65     vp.dvClipWidth  = 2.0f;
66     vp.dvClipY      = 1.0f;
67     vp.dvClipHeight = 2.0f;
68 }
69
70
71
72
73 //-----------------------------------------------------------------------------
74 // Name: D3DUtil_InitMaterial()
75 // Desc: Helper function called to build a D3DMATERIAL structure
76 //-----------------------------------------------------------------------------
77 VOID D3DUtil_InitMaterial( D3DMATERIAL& mtrl, FLOAT r, FLOAT g, FLOAT b )
78 {
79     ZeroMemory( &mtrl, sizeof(D3DMATERIAL) );
80     mtrl.dwSize       = sizeof(D3DMATERIAL);
81     mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
82     mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
83     mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
84     mtrl.dwRampSize   = 16L; // A default ramp size
85 }
86
87
88
89
90 //-----------------------------------------------------------------------------
91 // Name: D3DUtil_InitLight()
92 // Desc: Initializes a D3DLIGHT structure
93 //-----------------------------------------------------------------------------
94 VOID D3DUtil_InitLight( D3DLIGHT& light, D3DLIGHTTYPE ltType, 
95                         FLOAT x, FLOAT y, FLOAT z )
96 {
97     ZeroMemory( &light, sizeof(D3DLIGHT) );
98     light.dwSize       = sizeof(D3DLIGHT);
99     light.dltType      = ltType;
100     light.dcvColor.r   = 1.0f;
101     light.dcvColor.g   = 1.0f;
102     light.dcvColor.b   = 1.0f;
103     light.dvPosition.x = light.dvDirection.x = x;
104     light.dvPosition.y = light.dvDirection.y = y;
105     light.dvPosition.z = light.dvDirection.z = z;
106 }
107
108
109
110
111 //-----------------------------------------------------------------------------
112 // Name: D3DUtil_GetDirectDrawFromDevice()
113 // Desc: Get the DDraw interface from a D3DDevice.
114 //-----------------------------------------------------------------------------
115 LPDIRECTDRAW4 D3DUtil_GetDirectDrawFromDevice( LPDIRECT3DDEVICE3 pd3dDevice )
116 {
117         LPDIRECTDRAW4        pDD = NULL;
118         LPDIRECTDRAWSURFACE4 pddsRender;
119
120     if( pd3dDevice )
121         {
122             // Get the current render target
123                 if( SUCCEEDED( pd3dDevice->GetRenderTarget( &pddsRender ) ) )
124                 {
125                     // Get the DDraw4 interface from the render target
126                         pddsRender->GetDDInterface( (VOID**)&pDD );
127                         pddsRender->Release();
128                 }
129         }
130         return pDD;
131 }
132
133
134
135
136 //-----------------------------------------------------------------------------
137 // Name: D3DUtil_GetDeviceMemoryType()
138 // Desc: Retreives the default memory type used for the device.
139 //-----------------------------------------------------------------------------
140 DWORD D3DUtil_GetDeviceMemoryType( LPDIRECT3DDEVICE3 pd3dDevice )
141 {
142         D3DDEVICEDESC ddHwDesc, ddSwDesc;
143         ddHwDesc.dwSize = sizeof(D3DDEVICEDESC);
144         ddSwDesc.dwSize = sizeof(D3DDEVICEDESC);
145         if( FAILED( pd3dDevice->GetCaps( &ddHwDesc, &ddSwDesc ) ) )
146                 return 0L;
147
148         if( ddHwDesc.dwFlags )
149                 return DDSCAPS_VIDEOMEMORY;
150
151         return DDSCAPS_SYSTEMMEMORY;
152 }
153
154
155
156
157 //-----------------------------------------------------------------------------
158 // Name: D3DUtil_SetViewMatrix()
159 // Desc: Given an eye point, a lookat point, and an up vector, this
160 //       function builds a 4x4 view matrix.
161 //-----------------------------------------------------------------------------
162 HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, 
163                                D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
164 {
165     // Get the z basis vector, which points straight ahead. This is the
166     // difference from the eyepoint to the lookat point.
167     D3DVECTOR vView = vAt - vFrom;
168
169     FLOAT fLength = Magnitude( vView );
170     if( fLength < 1e-6f )
171         return E_INVALIDARG;
172
173     // Normalize the z basis vector
174     vView /= fLength;
175
176     // Get the dot product, and calculate the projection of the z basis
177     // vector onto the up vector. The projection is the y basis vector.
178     FLOAT fDotProduct = DotProduct( vWorldUp, vView );
179
180     D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
181
182     // If this vector has near-zero length because the input specified a
183     // bogus up vector, let's try a default up vector
184     if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
185     {
186         vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
187
188         // If we still have near-zero length, resort to a different axis.
189         if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
190         {
191             vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
192
193             if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
194                 return E_INVALIDARG;
195         }
196     }
197
198     // Normalize the y basis vector
199     vUp /= fLength;
200
201     // The x basis vector is found simply with the cross product of the y
202     // and z basis vectors
203     D3DVECTOR vRight = CrossProduct( vUp, vView );
204     
205     // Start building the matrix. The first three rows contains the basis
206     // vectors used to rotate the view to point at the lookat point
207     D3DUtil_SetIdentityMatrix( mat );
208     mat._11 = vRight.x;    mat._12 = vUp.x;    mat._13 = vView.x;
209     mat._21 = vRight.y;    mat._22 = vUp.y;    mat._23 = vView.y;
210     mat._31 = vRight.z;    mat._32 = vUp.z;    mat._33 = vView.z;
211
212     // Do the translation values (rotations are still about the eyepoint)
213     mat._41 = - DotProduct( vFrom, vRight );
214     mat._42 = - DotProduct( vFrom, vUp );
215     mat._43 = - DotProduct( vFrom, vView );
216
217     return S_OK;
218 }
219
220
221
222
223 //-----------------------------------------------------------------------------
224 // Name: D3DUtil_SetProjectionMatrix()
225 // Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
226 //       from the field-of-view (fov, in y), aspect ratio, near plane (D),
227 //       and far plane (F). Note that the projection matrix is normalized for
228 //       element [3][4] to be 1.0. This is performed so that W-based range fog
229 //       will work correctly.
230 //-----------------------------------------------------------------------------
231 HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
232                                      FLOAT fNearPlane, FLOAT fFarPlane )
233 {
234     if( fabs(fFarPlane-fNearPlane) < 0.01f )
235         return E_INVALIDARG;
236     if( fabs(sin(fFOV/2)) < 0.01f )
237         return E_INVALIDARG;
238
239         FLOAT w = fAspect * (FLOAT)( cos(fFOV/2)/sin(fFOV/2) );
240         FLOAT h =   1.0f  * (FLOAT)( cos(fFOV/2)/sin(fFOV/2) );
241     FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
242
243     ZeroMemory( &mat, sizeof(D3DMATRIX) );
244     mat._11 = w;
245     mat._22 = h;
246     mat._33 = Q;
247     mat._34 = 1.0f;
248     mat._43 = -Q*fNearPlane;
249
250     return S_OK;
251 }
252
253
254
255
256 //-----------------------------------------------------------------------------
257 // Name: D3DUtil_SetRotateXMatrix()
258 // Desc: Create Rotation matrix about X axis
259 //-----------------------------------------------------------------------------
260 VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
261 {
262     D3DUtil_SetIdentityMatrix( mat );
263     mat._22 =  (FLOAT)cos( fRads );
264     mat._23 =  (FLOAT)sin( fRads );
265     mat._32 = -(FLOAT)sin( fRads );
266     mat._33 =  (FLOAT)cos( fRads );
267 }
268
269
270
271
272 //-----------------------------------------------------------------------------
273 // Name: D3DUtil_SetRotateYMatrix()
274 // Desc: Create Rotation matrix about Y axis
275 //-----------------------------------------------------------------------------
276 VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
277 {
278     D3DUtil_SetIdentityMatrix( mat );
279     mat._11 =  (FLOAT)cos( fRads );
280     mat._13 = -(FLOAT)sin( fRads );
281     mat._31 =  (FLOAT)sin( fRads );
282     mat._33 =  (FLOAT)cos( fRads );
283 }
284
285
286
287
288 //-----------------------------------------------------------------------------
289 // Name: D3DUtil_SetRotateZMatrix()
290 // Desc: Create Rotation matrix about Z axis
291 //-----------------------------------------------------------------------------
292 VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
293 {
294     D3DUtil_SetIdentityMatrix( mat );
295     mat._11  =  (FLOAT)cos( fRads );
296     mat._12  =  (FLOAT)sin( fRads );
297     mat._21  = -(FLOAT)sin( fRads );
298     mat._22  =  (FLOAT)cos( fRads );
299 }
300
301
302
303
304 //-----------------------------------------------------------------------------
305 // Name: D3DUtil_SetRotationMatrix
306 // Desc: Create a Rotation matrix about vector direction 
307 //-----------------------------------------------------------------------------
308 VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
309 {
310     FLOAT     fCos = (FLOAT)cos( fRads );
311     FLOAT     fSin = (FLOAT)sin( fRads );
312     D3DVECTOR v    = Normalize( vDir );
313
314     mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
315     mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
316     mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
317
318     mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
319     mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
320     mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
321
322     mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
323     mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
324     mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
325     
326     mat._14 = mat._24 = mat._34 = 0.0f;
327     mat._41 = mat._42 = mat._43 = 0.0f;
328     mat._44 = 1.0f;
329
330
331
332
333
334 //-----------------------------------------------------------------------------
335 // Name: D3DUtil_GetDisplayDepth()
336 // Desc: Returns the depth of the current display mode.
337 //-----------------------------------------------------------------------------
338 DWORD D3DUtil_GetDisplayDepth( LPDIRECTDRAW4 pDD4 )
339 {
340         // If the caller did not supply a DDraw object, just create a temp one.
341         if( NULL == pDD4 )
342         {
343                 LPDIRECTDRAW pDD1;
344                 if( FAILED( DirectDrawCreate( NULL, &pDD1, NULL ) ) )
345                         return 0L;
346         
347                 HRESULT hr = pDD1->QueryInterface( IID_IDirectDraw4, (VOID**)&pDD4 );
348                 pDD1->Release();
349                 if( FAILED(hr) )
350                         return 0L;
351         }
352         else
353                 pDD4->AddRef();
354
355         // Get the display mode description
356         DDSURFACEDESC2 ddsd;
357         ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
358         ddsd.dwSize = sizeof(DDSURFACEDESC2);
359         pDD4->GetDisplayMode( &ddsd );
360         pDD4->Release();
361
362         // Return the display mode's depth
363         return ddsd.ddpfPixelFormat.dwRGBBitCount;
364 }
365
366
367
368
369 //-----------------------------------------------------------------------------
370 // Name: _DbgOut()
371 // Desc: Outputs a message to the debug stream
372 //-----------------------------------------------------------------------------
373 HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
374 {
375     TCHAR buffer[256];
376     sprintf( buffer, "%s(%ld): ", strFile, dwLine );
377     OutputDebugString( buffer );
378     OutputDebugString( strMsg );
379     
380     if( hr )
381     {
382         sprintf( buffer, "(hr=%08lx)\n", hr );
383         OutputDebugString( buffer );
384     }
385
386     OutputDebugString( "\n" );
387     
388     return hr;
389 }
390