MercuryDisplay_D3D.cpp

Go to the documentation of this file.
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;       //screen width
00071     m_PresentParameters.BackBufferHeight = height;     //screen height
00072     m_PresentParameters.BackBufferFormat = (bits==16)?D3DFMT_R5G6B5:D3DFMT_X8R8G8B8;
00073                     // D3DFMT_A8R8G8B8 and D3DFMT_X8R8G8B8 are the other options
00074     m_PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; //anti-aliasing
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     // to do, here, use GetBackBuffer and UpdateSurface (to blit the image)
00126     //
00127 }
00128 /*
00129 void MercuryDisplay_D3D::DrawGeometry(const MercuryGeometry& g, const MercuryMesh& mesh)
00130 {
00131     IDirect3DVertexBuffer9 *ID3VB;
00132     HRESULT T;
00133     T = m_pDirect3DDevice->CreateVertexBuffer(
00134         mesh.NumVertices() * sizeof( MercuryVertex ),
00135         0,
00136         D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1,
00137         D3DPOOL_SYSTEMMEM,
00138         &ID3VB,
00139         NULL );
00140 
00141     VOID* pVertices;
00142 
00143     if(FAILED(ID3VB->Lock(0, sizeof(MercuryVertex) * mesh.NumVertices( ), 
00144         (void**)&pVertices, 0 ) ) ) 
00145             return; //??go figure
00146     memcpy( pVertices, mesh.GetVerticePtr(), mesh.NumVertices() );
00147     ID3VB->Unlock();
00148     int i = m_pDirect3DDevice->SetStreamSource( 0, ID3VB, 0, sizeof( MercuryVertex ) );
00149     i = m_pDirect3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, mesh.NumVertices() );
00150     m_verticesDrawn += mesh.NumVertices();
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     //Notice that we set levels to 1 here. This is because we don't yet support mipmaps for DirectX
00197     IDirect3DTexture9 * s = NULL;
00198     //int i = m_pDirect3DDevice->CreateTexture
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         //How annoying! DirectX doesn't support Luminance Alpha.
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         //DirectX doesn't allow alpha at end, unlike everything else, so we have to flip it.
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     //Not yet implemented
00380 }
00381 
00382 void MercuryDisplay_D3D::DefineClippingPlanes( const MVector<MQuaternion> & planes )
00383 {
00384     //Not yet implemented
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     //XXX Not yet implemented
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; //??go figure
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 //Used guide from http://www.two-kings.de/tutorials/dxgraphics/dxgraphics02.html
00475 //  for help.
00476 
00477 /* 
00478  * Copyright (c) 2006 Joshua Allen, Charles Lohr
00479  * All rights reserved.
00480  *
00481  * Redistribution and use in source and binary forms, with or
00482  * without modification, are permitted provided that the following
00483  * conditions are met:
00484  *  -   Redistributions of source code must retain the above
00485  *      copyright notice, this list of conditions and the following disclaimer.
00486  *  -   Redistributions in binary form must reproduce the above copyright
00487  *      notice, this list of conditions and the following disclaimer in
00488  *      the documentation and/or other materials provided with the distribution.
00489  *  -   Neither the name of the Mercury Engine nor the names of its
00490  *      contributors may be used to endorse or promote products derived from
00491  *      this software without specific prior written permission.
00492  *
00493  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00494  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00495  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00496  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00497  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00498  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00499  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00500  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00501  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00502  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00503  */

Hosted by SourceForge.net Logo