00001 #if defined( USE_D3D )
00002
00003 #define MCOLOR_TO_DX_COLOR( mc ) (*((D3DCOLORVALUE*)(void*)&mc))
00004 #define MPOINT_TO_DX_VECTOR( mc ) (*((D3DVECTOR*)(void*)&mc))
00005 #include <D3D9.h>
00006 #include <D3dx9math.h>
00007 #include <D3DX9Core.h>
00008
00009 #include "MercuryDisplay_D3D.h"
00010 #include "MercuryObject.h"
00011 #include "MercuryLog.h"
00012
00013 #if defined(_MSC_VER)
00014 #pragma comment(lib, "D3dx9.lib")
00015 #pragma comment(lib, "D3d9.lib")
00016 #pragma comment(lib, "Dxerr9.lib")
00017 #endif
00018
00019 MercuryDisplay_D3D::~MercuryDisplay_D3D()
00020 {
00021 if(m_pDirect3DDevice != NULL)
00022 {
00023 m_pDirect3DDevice->Release();
00024 m_pDirect3DDevice = NULL;
00025 }
00026
00027 if(m_d3d != NULL)
00028 {
00029 m_d3d->Release();
00030 m_d3d = NULL;
00031 }
00032 }
00033
00034 MercuryDisplay_D3D::MercuryDisplay_D3D()
00035 {
00036 MercuryDisplay::MercuryDisplay();
00037 }
00038
00039 bool MercuryDisplay_D3D::MakeWindow(const char* title, int width, int height, int bits, bool fullscreenflag)
00040 {
00041 m_pDirect3DDevice = NULL;
00042
00043 if (m_window == NULL)
00044 return false;
00045
00046
00047 if (!m_window->MakeRender(title, width, height, bits, fullscreenflag, RT_D3D))
00048 {
00049 LOG.Warn( "Failed to make Renderer" );
00050 m_window->DestroyWindowAndRender();
00051 return false;
00052 }
00053
00054 m_d3d = Direct3DCreate9( D3D_SDK_VERSION );
00055
00056 if( m_d3d == NULL )
00057 {
00058 LOG.Warn( "Could not create Direct3D Object" );
00059 return false;
00060 }
00061
00062 ZeroMemory(&m_PresentParameters,sizeof(m_PresentParameters));
00063
00064 m_PresentParameters.Windowed = !fullscreenflag;
00065 m_PresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
00066 m_PresentParameters.EnableAutoDepthStencil = true;
00067 m_PresentParameters.AutoDepthStencilFormat = D3DFMT_D16;
00068 m_PresentParameters.hDeviceWindow = (HWND)m_window->m_hWnd;
00069
00070 m_PresentParameters.BackBufferWidth = width;
00071 m_PresentParameters.BackBufferHeight = height;
00072 m_PresentParameters.BackBufferFormat = (bits==16)?D3DFMT_R5G6B5:D3DFMT_X8R8G8B8;
00073
00074 m_PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
00075
00076 if( FAILED( m_d3d->CreateDevice(
00077 D3DADAPTER_DEFAULT,
00078 D3DDEVTYPE_HAL,
00079 (HWND)m_window->m_hWnd,
00080 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
00081 &m_PresentParameters,
00082 &m_pDirect3DDevice)))
00083 {
00084 LOG.Warn( "Could not create Direct3D Device" );
00085 return false;
00086 }
00087
00088 Viewport( 0,0, m_window->GetWidth(), m_window->GetHeight() );
00089
00090 return MercuryDisplay::MakeWindow( title, width, height, bits, fullscreenflag );
00091 }
00092
00093 void MercuryDisplay_D3D::Init()
00094 {
00095 MercuryDisplay::Init();
00096 }
00097
00098 bool MercuryDisplay_D3D::BeginFrame()
00099 {
00100 m_pDirect3DDevice->Clear(
00101 0,
00102 NULL,
00103 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
00104 D3DCOLOR_XRGB(0,0,255),
00105 1.0f,
00106 0);
00107 if( !m_pDirect3DDevice->BeginScene() )
00108 return false;
00109
00110 return true;
00111 }
00112
00113 bool MercuryDisplay_D3D::EndFrame()
00114 {
00115 m_pDirect3DDevice->EndScene();
00116 m_pDirect3DDevice->Present( NULL, NULL, NULL, NULL );
00117 m_window->SwapBuffers();
00118 return true;
00119 }
00120
00121 void MercuryDisplay_D3D::DrawParticleField(const MercuryParticleField* field)
00122 {
00123 MDequeIterator<MercuryObject::ParentHoldPair> i = field->m_objects.begin();
00124
00125
00126
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 void MercuryDisplay_D3D::SetMaterial(const MercuryMaterial* material)
00154 {
00155 }
00156
00157 void MercuryDisplay_D3D::RendererInfo()
00158 {
00159 }
00160
00161 void MercuryDisplay_D3D::ClearZBuffer()
00162 {
00163 m_pDirect3DDevice->Clear(
00164 0,
00165 NULL,
00166 D3DCLEAR_ZBUFFER,
00167 D3DCOLOR_XRGB(0,0,0),
00168 1.0f,
00169 0);
00170 }
00171
00172 void MercuryDisplay_D3D::DeleteTextures(int n, unsigned int* textureNames)
00173 {
00174 for( unsigned i = 0; i < n; ++i )
00175 {
00176 m_vSurfaces[textureNames[i]]->Release();;
00177 m_vFreeSurfaces.push_back(textureNames[i]);
00178 }
00179 }
00180
00181 void MercuryDisplay_D3D::UpdateTextureData(MercuryTexture* texture, unsigned int& ID)
00182 {
00183 UpdateTextureData( texture->GetRaw(), texture->GetWidth(), texture->GetHeight(), texture->GetColorByteType(), ID );
00184 }
00185
00186 void MercuryDisplay_D3D::UpdateTextureData(unsigned char*ib, int w, int h, ColorBytes cb, unsigned int& ID)
00187 {
00188 unsigned char * buf;
00189 unsigned p;
00190 RECT c;
00191 c.top = 0;
00192 c.left = 0;
00193 c.right = w;
00194 c.bottom = h;
00195
00196
00197 IDirect3DTexture9 * s = NULL;
00198
00199
00200 int i = D3DXCreateTexture( m_pDirect3DDevice,
00201 w, h, 1, D3DUSAGE_DYNAMIC,
00202 (cb==RGB)?D3DFMT_R8G8B8:D3DFMT_A8R8G8B8,
00203 D3DPOOL_SYSTEMMEM, &s );
00204
00205 if( FAILED( i ) )
00206 return;
00207
00208 m_vSurfaces[ID] = s;
00209
00210 D3DLOCKED_RECT lri;
00211 i = s->LockRect( 0, &lri, &c, D3DLOCK_NOSYSLOCK );
00212
00213 if( FAILED( i ) )
00214 return;
00215
00216 IDirect3DSurface9 * surf;
00217
00218 s->GetSurfaceLevel( 0, &surf );
00219
00220 switch( cb )
00221 {
00222 case BLANK:
00223 case BLANK1:
00224 break;
00225 case LUMINANCE_ALPHA:
00226
00227 buf = new unsigned char[c.right*c.bottom*2];
00228
00229 for( p = 0; p < c.right*c.bottom; ++p )
00230 {
00231 buf[p*4+0] = ib[p*2+1];
00232 buf[p*4+1] = ib[p*2+0];
00233 buf[p*4+2] = ib[p*2+0];
00234 buf[p*4+3] = ib[p*2+0];
00235 }
00236
00237 D3DXLoadSurfaceFromMemory( surf, 0, 0, buf,
00238 D3DFMT_R8G8B8, w * 3, NULL, &c, D3DX_DEFAULT, 0 );
00239 break;
00240
00241 delete buf;
00242 break;
00243 case RGB:
00244 D3DXLoadSurfaceFromMemory( surf, 0, 0, ib,
00245 D3DFMT_R8G8B8, w * 3, NULL, &c, D3DX_DEFAULT, 0 );
00246 break;
00247 case RGBA:
00248
00249
00250 buf = new unsigned char[c.right*c.bottom*4];
00251
00252 for( p = 0; p < c.right*c.bottom; ++p )
00253 {
00254 buf[p*4+0] = ib[p*4+3];
00255 buf[p*4+1] = ib[p*4+0];
00256 buf[p*4+2] = ib[p*4+1];
00257 buf[p*4+3] = ib[p*4+2];
00258 }
00259
00260 D3DXLoadSurfaceFromMemory( surf, 0, 0, buf,
00261 D3DFMT_R8G8B8, w * 3, NULL, &c, D3DX_DEFAULT, 0 );
00262 delete buf;
00263
00264 break;
00265 }
00266
00267 s->UnlockRect( 0 );
00268 }
00269
00270 void MercuryDisplay_D3D::CreateCache(MercuryTexture* texture, unsigned int& ID)
00271 {
00272 ID = AllocTex();
00273 UpdateTextureData( texture->GetRaw(), texture->GetWidth(), texture->GetHeight(), texture->GetColorByteType(), ID );
00274 }
00275
00276 void MercuryDisplay_D3D::CreateCache(RawImageData* data, unsigned int& ID)
00277 {
00278 ID = AllocTex();
00279 UpdateTextureData( data->data, data->attrs.m_width, data->attrs.m_height, data->attrs.m_ColorByteType, ID );
00280 }
00281
00282 int MercuryDisplay_D3D::AllocTex()
00283 {
00284 if( !m_vFreeSurfaces.empty() )
00285 {
00286 int c = m_vFreeSurfaces.front();
00287 m_vFreeSurfaces.pop_back();
00288 return c;
00289 }
00290
00291 m_vSurfaces.resize( m_vSurfaces.size() + 1 );
00292 return m_vSurfaces.size()-1;
00293 }
00294
00295 void MercuryDisplay_D3D::EnablePixelshader()
00296 {
00297 }
00298
00299 void MercuryDisplay_D3D::DisablePixelshader()
00300 {
00301 }
00302
00303 void MercuryDisplay_D3D::EnableAllLighting()
00304 {
00305 m_pDirect3DDevice->SetRenderState( D3DRS_LIGHTING, true );
00306 }
00307
00308 void MercuryDisplay_D3D::DisableAllLighting()
00309 {
00310 m_pDirect3DDevice->SetRenderState( D3DRS_LIGHTING, false );
00311 }
00312
00313
00314 void MercuryDisplay_D3D::EnableDepthTest()
00315 {
00316 m_pDirect3DDevice->SetRenderState( D3DRS_ZENABLE, true );
00317 }
00318
00319 void MercuryDisplay_D3D::DisableDepthTest()
00320 {
00321 m_pDirect3DDevice->SetRenderState( D3DRS_ZENABLE, false );
00322 }
00323
00324 void MercuryDisplay_D3D::Viewport(int x, int y, int width, int height)
00325 {
00326 if( !m_pDirect3DDevice )
00327 return;
00328 D3DVIEWPORT9 vp;
00329
00330 vp.X = x; vp.Y = y; vp.Width = width; vp.Height = height;
00331
00333 vp.MinZ = 0; vp.MaxZ = 1;
00334
00335 m_pDirect3DDevice->SetViewport( &vp );
00336 }
00337
00338 void MercuryDisplay_D3D::ErrorCheck()
00339 {
00340 }
00341
00342 void MercuryDisplay_D3D::ReadFrameBuffer(RawImageData& image)
00343 {
00344 }
00345
00346 void MercuryDisplay_D3D::ProcessLightsInternal( const MercuryLight * light[], unsigned int count )
00347 {
00348 for (unsigned int i = 0; i < count; ++i)
00349 {
00350 if (!light[i])
00351 continue;
00352
00353 D3DLIGHT9 l;
00354 l.Type = ( light[i]->GetLightType() == LT_DIRECTIONAL )?D3DLIGHT_DIRECTIONAL:D3DLIGHT_POINT;
00355
00356 const MercuryMaterial& m = light[i]->GetFinalMaterial();
00357 l.Diffuse = MCOLOR_TO_DX_COLOR(m.m_diffuse);
00358 l.Specular = MCOLOR_TO_DX_COLOR(m.m_ambient);
00359 l.Ambient = MCOLOR_TO_DX_COLOR(m.m_specular);
00360 l.Position = MPOINT_TO_DX_VECTOR(light[i]->GetPosition());
00361 l.Direction = MPOINT_TO_DX_VECTOR(light[i]->GetPosition());
00362 l.Range = 1000;
00363 l.Falloff = 0;
00364 l.Attenuation0 = light[i]->GetAttenuation( Attenuation::CONSTANT ).value;
00365 l.Attenuation1 = light[i]->GetAttenuation( Attenuation::LINEAR ).value;
00366 l.Attenuation2 = light[i]->GetAttenuation( Attenuation::QUADRATIC ).value;
00367 l.Theta = 0;
00368 l.Phi = 0;
00369
00370 }
00371 }
00372
00373 void MercuryDisplay_D3D::DisableOldLights()
00374 {
00375 }
00376
00377 void MercuryDisplay_D3D::RenderTranslucentObject()
00378 {
00379
00380 }
00381
00382 void MercuryDisplay_D3D::DefineClippingPlanes( const MVector<MQuaternion> & planes )
00383 {
00384
00385 }
00386
00387 int MercuryDisplay_D3D::CompileShader( MString vertStr, MString fragStr )
00388 {
00389 return -1;
00390 }
00391
00392 void MercuryDisplay_D3D::StencilFunc( TFUNCT func, int ref, unsigned int zref )
00393 {
00394
00395 }
00396
00397 void MercuryDisplay_D3D::CullBackface( bool toggle )
00398 {
00399 m_pDirect3DDevice->SetRenderState( D3DRS_CULLMODE, toggle );
00400 }
00401
00402 void MercuryDisplay_D3D::StencilOp( STENCILOPS fail, STENCILOPS zfail, STENCILOPS zpass )
00403 {
00404 }
00405
00406 void MercuryDisplay_D3D::ToggleStencilBufferWrite( bool toggle )
00407 {
00408 }
00409
00410 void MercuryDisplay_D3D::ToggleColorMask( bool toggle )
00411 {
00412 }
00413
00414 void MercuryDisplay_D3D::ToggleZBufferWrite( bool toggle )
00415 {
00416 m_pDirect3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, toggle );
00417 }
00418
00419
00420 void MercuryDisplay_D3D::SendProjectionMatrixData()
00421 {
00422 m_pDirect3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&GetProjection() );
00423 }
00424
00425 void MercuryDisplay_D3D::SendMatrixData( const MercuryMatrix & m )
00426 {
00427 m_pDirect3DDevice->SetTransform( D3DTS_VIEW, (D3DMATRIX*)&ViewStack.GetTop() );
00428 m_pDirect3DDevice->SetTransform( D3DTS_WORLDMATRIX(0), (D3DMATRIX*)&m );
00429 }
00430
00431 void MercuryDisplay_D3D::EnableTextures(MercuryMaterial* material)
00432 {
00433 m_pDirect3DDevice->SetMaterial( (D3DMATERIAL9*)(&material->m_diffuse) );
00434 for( unsigned i = 0; i < material->NumTextures(); ++i )
00435 m_pDirect3DDevice->SetTexture( i, m_vSurfaces[material->GetTexture( i )->GetID()] );
00436 }
00437
00438 void MercuryDisplay_D3D::DrawNoGeometry( const MercuryMesh & mesh, DRAWTYPES drawtype )
00439 {
00440 IDirect3DVertexBuffer9 *ID3VB;
00441 HRESULT T;
00442 T = m_pDirect3DDevice->CreateVertexBuffer(
00443 mesh.NumVertices() * sizeof( MercuryVertex ),
00444 0,
00445 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1,
00446 D3DPOOL_SYSTEMMEM,
00447 &ID3VB,
00448 NULL );
00449
00450 VOID* pVertices;
00451
00452 if(FAILED(ID3VB->Lock(0, sizeof(MercuryVertex) * mesh.NumVertices( ),
00453 (void**)&pVertices, 0 ) ) )
00454 return;
00455 memcpy( pVertices, mesh.GetVerticePtr(), mesh.NumVertices() );
00456 ID3VB->Unlock();
00457 int i = m_pDirect3DDevice->SetStreamSource( 0, ID3VB, 0, sizeof( MercuryVertex ) );
00458 i = m_pDirect3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, mesh.NumVertices() );
00459 m_verticesDrawn += mesh.NumVertices();
00460 }
00461
00462 void MercuryDisplay_D3D::RenderText(const MercuryText& text)
00463 {
00464 }
00465
00466 void MercuryDisplay_D3D::DrawSprite(const MercuryMesh& sprite)
00467 {
00468 }
00469
00470
00471
00472 #endif //END: USE_D3D
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503