Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreD3D7RenderSystem.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004 (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://ogre.sourceforge.net/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include <malloc.h>
    00026 #include "OgreD3D7RenderSystem.h"
    00027 #include "OgreDDDriver.h"
    00028 #include "OgreD3D7Device.h"
    00029 #include "OgreD3D7DeviceList.h"
    00030 #include "OgreDDDriverList.h"
    00031 #include "OgreDDVideoModeList.h"
    00032 #include "OgreDDVideoMode.h"
    00033 #include "OgreRenderWindow.h"
    00034 #include "OgreLogManager.h"
    00035 #include "OgreRenderSystem.h"
    00036 #include "OgreException.h"
    00037 #include "OgreSceneManager.h"
    00038 #include "OgreD3D7TextureManager.h"
    00039 #include "OgreViewport.h"
    00040 #include "OgreLight.h"
    00041 #include "OgreMatrix4.h"
    00042 #include "OgreMath.h"
    00043 #include "OgreD3D7RenderWindow.h"
    00044 #include "OgreFrustum.h"
    00045 #include "OgreD3D7GpuProgramManager.h"
    00046
    00047
    00048 namespace Ogre {
    00049     const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(
    00050         0.5,    0,  0, -0.5,
    00051         0, -0.5,  0, -0.5,
    00052         0,    0,  0,   1,
    00053         0,    0,  0,   1);
    00054
    00055     const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO(
    00056         -0.5,    0,  0, -0.5,
    00057         0, 0.5,  0, -0.5,
    00058         0,    0,  0,   1,
    00059         0,    0,  0,   1);
    00060
    00061     //-----------------------------------------------------------------------
    00062     D3DRenderSystem::D3DRenderSystem(HINSTANCE hInstance)
    00063     {
    00064         OgreGuard( "D3DRenderSystem::D3DRenderSystem" );
    00065
    00066         LogManager::getSingleton().logMessage(getName() + " created.");
    00067
    00068         mlpD3DDevice = NULL;
    00069         // Reset driver list
    00070         mDriverList = NULL;
    00071         mActiveDDDriver = NULL;
    00072         mhInstance = hInstance;
    00073         mHardwareBufferManager = NULL;
    00074         mGpuProgramManager = NULL;
    00075
    00076         initConfigOptions();
    00077
    00078         // Initialise D3DX library
    00079         D3DXInitialize();
    00080
    00081         // set stages desc. to defaults
    00082         for (int n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++)
    00083         {
    00084             mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
    00085             mTexStageDesc[n].coordIndex = 0;
    00086             mTexStageDesc[n].texType = D3D_TEX_TYPE_NORMAL;
    00087             mTexStageDesc[n].pTex = NULL;
    00088         }
    00089
    00090         mCurrentLights = 0;
    00091
    00092         OgreUnguard();
    00093     }
    00094
    00095     //-----------------------------------------------------------------------
    00096     D3DRenderSystem::~D3DRenderSystem()
    00097     {
    00098         OgreGuard( "D3DRenderSystem::~D3DRenderSystem" );
    00099         shutdown();
    00100
    00101         SAFE_DELETE(mTextureManager);
    00102         SAFE_DELETE(mDriverList);
    00103         SAFE_DELETE(mCapabilities);
    00104         SAFE_DELETE(mHardwareBufferManager);
    00105         SAFE_DELETE(mGpuProgramManager);
    00106
    00107         D3DXUninitialize();
    00108         LogManager::getSingleton().logMessage(getName() + " destroyed.");
    00109
    00110         OgreUnguard();
    00111     }
    00112
    00113     //-----------------------------------------------------------------------
    00114     const String& D3DRenderSystem::getName(void) const
    00115     {
    00116         static String strName("Direct3D7 Rendering Subsystem");
    00117         return strName;
    00118     }
    00119
    00120     //-----------------------------------------------------------------------
    00121     void D3DRenderSystem::initConfigOptions(void)
    00122     {
    00123         OgreGuard( "D3DRenderSystem::initConfigOptions" );
    00124
    00125         DDDriverList* ddList;
    00126         DDDriver* dd;
    00127
    00128         ConfigOption optDevice;
    00129         ConfigOption optVideoMode;
    00130         ConfigOption optFullScreen;
    00131         ConfigOption optVSync;
    00132
    00133         ddList = this->getDirectDrawDrivers();
    00134
    00135         // Create option for devices
    00136         optDevice.name = "Rendering Device";
    00137         optDevice.currentValue = "";
    00138         optDevice.possibleValues.clear();
    00139         optDevice.immutable = false;
    00140
    00141         // Option for video modes
    00142         optVideoMode.name = "Video Mode";
    00143         optVideoMode.currentValue = "";
    00144         optVideoMode.immutable = false;
    00145
    00146         // Option for full screen
    00147         optFullScreen.name = "Full Screen";
    00148         optFullScreen.possibleValues.push_back("Yes");
    00149         optFullScreen.possibleValues.push_back("No");
    00150         optFullScreen.currentValue = "Yes";
    00151
    00152
    00153         unsigned k = ddList->count();
    00154         // First, get DirectDraw driver options
    00155         for( unsigned j = 0; j < ddList->count(); j++ )
    00156         {
    00157             dd = ddList->item(j);
    00158             // Add to device option list
    00159             optDevice.possibleValues.push_back( dd->DriverDescription() );
    00160
    00161             // Make first one default
    00162             if( j==0 )
    00163             {
    00164                 optDevice.currentValue = dd->DriverDescription();
    00165
    00166             }
    00167
    00168
    00169         }
    00170
    00171         // VSync option
    00172         optVSync.name = "VSync";
    00173         optVSync.immutable = false;
    00174         optVSync.possibleValues.push_back("Yes");
    00175         optVSync.possibleValues.push_back("No");
    00176         optVSync.currentValue = "Yes";
    00177
    00178
    00179         mOptions[optDevice.name] = optDevice;
    00180         mOptions[optVideoMode.name] = optVideoMode;
    00181         mOptions[optFullScreen.name] = optFullScreen;
    00182         mOptions[optVSync.name] = optVSync;
    00183
    00184         // Set default-based settings
    00185         refreshDDSettings();
    00186
    00187         OgreUnguard();
    00188     }
    00189
    00190     //-----------------------------------------------------------------------
    00191     void D3DRenderSystem::refreshDDSettings(void)
    00192     {
    00193         OgreGuard( "D3DRenderSystem::refreshDDSettings" );
    00194
    00195         DDVideoMode* vid;
    00196         ConfigOption* optVideoMode;
    00197         ConfigOption* optFullScreen;
    00198         DDDriver* dd;
    00199
    00200         // Stuffs DD-Driver specific settings
    00201
    00202         // Find DD Driver selected in options
    00203         ConfigOptionMap::iterator opt = mOptions.find("Rendering Device");
    00204
    00205         if( opt != mOptions.end() )
    00206         {
    00207             for( unsigned j = 0; j < getDirectDrawDrivers()->count(); j++ )
    00208             {
    00209                 dd = getDirectDrawDrivers()->item(j);
    00210                 if( dd->DriverDescription() == opt->second.currentValue )
    00211                     break;
    00212             }
    00213
    00214             // Get fullScreen and Video mode options
    00215             opt = mOptions.find("Video Mode");
    00216             optVideoMode = &opt->second;
    00217             opt = mOptions.find("Full Screen");
    00218             optFullScreen = &opt->second;
    00219
    00220             // Full screen forced?
    00221             if (!(dd->CanRenderWindowed()))
    00222             {
    00223                 setConfigOption("Full Screen", "Yes");
    00224                 optFullScreen->immutable = true;
    00225             }
    00226             else
    00227                 optFullScreen->immutable = false;
    00228
    00229             // Get video modes for this device
    00230             optVideoMode->possibleValues.clear();
    00231
    00232             for( unsigned k = 0; k<dd->getVideoModeList()->count(); k++ )
    00233             {
    00234                 vid = dd->getVideoModeList()->item(k);
    00235                 optVideoMode->possibleValues.push_back(vid->Description());
    00236             }
    00237         }
    00238
    00239         OgreUnguard();
    00240     }
    00241
    00242
    00243     //-----------------------------------------------------------------------
    00244     ConfigOptionMap& D3DRenderSystem::getConfigOptions(void)
    00245     {
    00246         // Return a COPY of the current config options
    00247         return mOptions;
    00248
    00249     }
    00250
    00251     //-----------------------------------------------------------------------
    00252     void D3DRenderSystem::setConfigOption(const String &name, const String &value)
    00253     {
    00254         OgreGuard( "D3DRenderSystem::setConfigOption" );
    00255
    00256         char msg[128];
    00257
    00258         sprintf(msg, "RenderSystem Option: %s = %s", name.c_str(), value.c_str());
    00259         LogManager::getSingleton().logMessage(msg);
    00260
    00261         // Find option
    00262         ConfigOptionMap::iterator it = mOptions.find(name);
    00263
    00264         // Update
    00265         if( it != mOptions.end())
    00266             it->second.currentValue = value;
    00267         else
    00268         {
    00269             sprintf(msg, "Option named %s does not exist.", name.c_str());
    00270             Except(Exception::ERR_INVALIDPARAMS,
    00271                 msg, "D3DRenderSystem::setConfigOption");
    00272         }
    00273
    00274         // Refresh other options if DD Driver changed
    00275         if (name == "Rendering Device")
    00276             refreshDDSettings();
    00277
    00278         if (name == "Full Screen")
    00279         {
    00280             if (value == "No")
    00281             {
    00282                 // Video mode is not applicable
    00283                 it = mOptions.find("Video Mode");
    00284                 it->second.currentValue = "N/A";
    00285                 it->second.immutable = true;
    00286             }
    00287             else
    00288             {
    00289                 // Video mode is applicable
    00290                 it = mOptions.find("Video Mode");
    00291                 // default to 640 x 480 x 16
    00292                 it->second.currentValue = "640 x 480 @ 16-bit colour";
    00293                 it->second.immutable = false;
    00294             }
    00295         }
    00296
    00297         OgreUnguard();
    00298     }
    00299     //-----------------------------------------------------------------------
    00300     String D3DRenderSystem::validateConfigOptions(void)
    00301     {
    00302         // Check video mode specified in full screen mode
    00303         ConfigOptionMap::iterator o = mOptions.find("Full Screen");
    00304         if (o->second.currentValue == "Yes")
    00305         {
    00306             // Check video mode
    00307             o = mOptions.find("Video Mode");
    00308             if (o->second.currentValue == "")
    00309             {
    00310                 return "A video mode must be selected for running in full-screen mode.";
    00311             }
    00312         }
    00313
    00314         o = mOptions.find( "Rendering Device" );
    00315         bool foundDriver = false;
    00316         DDDriverList* driverList = getDirectDrawDrivers();
    00317         for( ushort j=0; j < driverList->count(); j++ )
    00318         {
    00319             if( driverList->item(j)->DriverDescription() == o->second.currentValue )
    00320             {
    00321                 foundDriver = true;
    00322                 break;
    00323             }
    00324         }
    00325         if (!foundDriver)
    00326         {
    00327             // Just pick the first driver
    00328             setConfigOption("Rendering Device", driverList->item(0)->DriverDescription());
    00329             return "Your DirectX driver name has changed since the last time you ran OGRE; "
    00330                 "the 'Rendering Device' has been changed.";
    00331         }
    00332         return "";
    00333
    00334     }
    00335     //-----------------------------------------------------------------------
    00336     RenderWindow* D3DRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
    00337     {
    00338         RenderWindow* autoWindow = 0;
    00339
    00340
    00341         LogManager::getSingleton().logMessage(
    00342             "***************************************\n"
    00343             "*** Direct3D Subsystem Initialising ***\n"
    00344             "***************************************" );
    00345
    00346         // ---------------------------
    00347         // Init using current settings
    00348         // ---------------------------
    00349
    00350         // DirectDraw driver
    00351         mActiveDDDriver = 0;
    00352         ConfigOptionMap::iterator opt = mOptions.find("Rendering Device");
    00353         for( unsigned j = 0; j<getDirectDrawDrivers()->count(); j++ )
    00354         {
    00355             if (getDirectDrawDrivers()->item(j)->DriverDescription() == opt->second.currentValue)
    00356             {
    00357                 mActiveDDDriver = getDirectDrawDrivers()->item(j);
    00358                 break;
    00359             }
    00360         }
    00361
    00362         if (!mActiveDDDriver)
    00363             Except(Exception::ERR_INVALIDPARAMS, "Problems finding requested DirectDraw driver!",
    00364             "D3DRenderSystem::initialise");
    00365
    00366
    00367         // Sort out the creation of a new window if required
    00368         if (autoCreateWindow)
    00369         {
    00370             // Full screen?
    00371             bool fullScreen;
    00372             opt = mOptions.find("Full Screen");
    00373             if( opt == mOptions.end() )
    00374                 Except(999, "Can't find full screen option!",
    00375                 "D3DRenderSystem::initialise");
    00376             if (opt->second.currentValue == "Yes")
    00377                 fullScreen = true;
    00378             else
    00379                 fullScreen = false;
    00380
    00381             // Get video mode
    00382             DDVideoMode* vid;
    00383             unsigned int height, width, colourDepth;
    00384
    00385             vid = 0;
    00386             String temp;
    00387             if (fullScreen)
    00388             {
    00389                 opt = mOptions.find("Video Mode");
    00390
    00391                 for( unsigned j=0; j<mActiveDDDriver->getVideoModeList()->count(); j++ )
    00392                 {
    00393                     temp = mActiveDDDriver->getVideoModeList()->item(j)->Description();
    00394                     if (temp == opt->second.currentValue)
    00395                     {
    00396                         vid = mActiveDDDriver->getVideoModeList()->item(j);
    00397                         break;
    00398                     }
    00399                 }
    00400
    00401                 if (!vid)
    00402                     Except(9999, "Can't find requested video mode.",
    00403                     "D3DRenderSystem::initilise");
    00404                 width = vid->mWidth;
    00405                 height = vid->mHeight;
    00406                 colourDepth = vid->mColourDepth;
    00407
    00408             }
    00409             else
    00410             {
    00411                 // Notional height / width
    00412                 width = 800;
    00413                 height = 600;
    00414                 colourDepth = 0; // colour depth based on desktop
    00415             }
    00416
    00417             // Create myself a window
    00418             autoWindow = this->createRenderWindow(windowTitle, width, height, colourDepth, fullScreen);
    00419
    00420             // If we have 16bit depth buffer enable w-buffering.
    00421             assert( autoWindow );
    00422             if ( autoWindow->getColourDepth() == 16 )
    00423             {
    00424                 mWBuffer = true;
    00425             }
    00426             else
    00427             {
    00428                 mWBuffer = false;
    00429             }
    00430
    00431         }
    00432
    00433         opt = mOptions.find("VSync");
    00434         if (opt!=mOptions.end())
    00435         {
    00436             if (opt->second.currentValue == "Yes")
    00437             {
    00438                 setWaitForVerticalBlank(true);
    00439             }
    00440             else
    00441             {
    00442                 setWaitForVerticalBlank(false);
    00443             }
    00444         }
    00445
    00446
    00447         LogManager::getSingleton().logMessage("*****************************************");
    00448         LogManager::getSingleton().logMessage("*** Direct3D Subsystem Initialised Ok ***");
    00449         LogManager::getSingleton().logMessage("*****************************************");
    00450
    00451         // call superclass method
    00452         RenderSystem::initialise(autoCreateWindow);
    00453
    00454         // Create buffer manager
    00455         mHardwareBufferManager = new D3D7HardwareBufferManager();
    00456         // Create dummy gpu manager
    00457         mGpuProgramManager = new D3D7GpuProgramManager();
    00458
    00459
    00460         return autoWindow;
    00461
    00462     }
    00463
    00464     //-----------------------------------------------------------------------
    00465     void D3DRenderSystem::reinitialise(void)
    00466     {
    00467         this->shutdown();
    00468         this->initialise(true);
    00469     }
    00470
    00471
    00472     //-----------------------------------------------------------------------
    00473     void D3DRenderSystem::shutdown(void)
    00474     {
    00475         RenderSystem::shutdown();
    00476
    00477         // Cleanup
    00478         // Release all DirectX resources
    00479         //D3DTextr_InvalidateAllTextures();
    00480         if (mActiveDDDriver)
    00481         {
    00482             mActiveDDDriver->Cleanup();
    00483         }
    00484
    00485         // Delete system objects
    00486         SAFE_DELETE(mDriverList);
    00487
    00488         mActiveDDDriver = NULL;
    00489
    00490
    00491
    00492         // Write termination message
    00493         LogManager::getSingleton().logMessage("*-*-* Direct3D Subsystem shutting down cleanly.");
    00494
    00495
    00496     }
    00497
    00498     //-----------------------------------------------------------------------
    00499     void D3DRenderSystem::setAmbientLight(float r, float g, float b)
    00500     {
    00501         // Call D3D
    00502         D3DCOLOR col = D3DRGB(r,g,b);
    00503
    00504         HRESULT hr = __SetRenderState(D3DRENDERSTATE_AMBIENT, col);
    00505         if (FAILED(hr))
    00506             Except(hr, "Error setting ambient light.", "D3DRenderSystem::setAmbientLight");
    00507     }
    00508
    00509     //-----------------------------------------------------------------------
    00510     void D3DRenderSystem::setShadingType(ShadeOptions so)
    00511     {
    00512         D3DSHADEMODE d3dMode;
    00513         switch(so)
    00514         {
    00515         case SO_FLAT:
    00516             d3dMode = D3DSHADE_FLAT;
    00517             break;
    00518         case SO_GOURAUD:
    00519             d3dMode = D3DSHADE_GOURAUD;
    00520             break;
    00521         case SO_PHONG:
    00522             d3dMode = D3DSHADE_PHONG;
    00523             break;
    00524
    00525         }
    00526
    00527         HRESULT hr = __SetRenderState(D3DRENDERSTATE_SHADEMODE, d3dMode);
    00528         if (FAILED(hr))
    00529             Except(hr, "Error setting shading mode.", "D3DRenderSystem::setShadingType");
    00530
    00531     }
    00532
    00533
    00534     //-----------------------------------------------------------------------
    00535     RenderWindow* D3DRenderSystem::createRenderWindow(const String &name, unsigned int width, unsigned int height, unsigned int colourDepth,
    00536         bool fullScreen, int left, int top, bool depthBuffer, RenderWindow* parentWindowHandle)
    00537     {
    00538         static bool firstWindow = true;
    00539         OgreGuard( "D3DRenderSystem::createRenderWindow" );
    00540
    00541         String msg;
    00542
    00543         // Make sure we don't already have a render target of the
    00544         // same name as the one supplied
    00545         if( mRenderTargets.find( name ) != mRenderTargets.end() )
    00546         {
    00547             msg = msg + "A render target of the same name (" + name + ") already "
    00548                 "exists. You cannot create a new window with this name.";
    00549             Except(999,msg,"D3DRenderSystem::createRenderWindow");
    00550         }
    00551
    00552         RenderWindow* win = new D3D7RenderWindow();
    00553         // Create window, supplying DD interface & hInstance
    00554         win->create(name, width, height, colourDepth, fullScreen,
    00555             left, top, depthBuffer, &mhInstance, mActiveDDDriver, parentWindowHandle);
    00556
    00557         attachRenderTarget( *win );
    00558
    00559         // If this is the first window, get the D3D device
    00560         //  and create the texture manager, setup caps
    00561         if (firstWindow)
    00562         {
    00563             win->getCustomAttribute("D3DDEVICE", &mlpD3DDevice);
    00564             // Get caps
    00565             mlpD3DDevice->GetCaps(&mD3DDeviceDesc);
    00566             // Create my texture manager for use by others
    00567             // Note this is a Singleton; pointer is held static by superclass
    00568             mTextureManager = new D3DTextureManager(mlpD3DDevice);
    00569
    00570             // Check for hardware stencil support
    00571             // Get render target, then depth buffer and check format
    00572             LPDIRECTDRAWSURFACE7 lpTarget;
    00573             win->getCustomAttribute("DDBACKBUFFER", &lpTarget);
    00574             DDSCAPS2 ddscaps;
    00575             ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
    00576             ddscaps.dwCaps = DDSCAPS_ZBUFFER;
    00577             lpTarget->GetAttachedSurface(&ddscaps, &lpTarget);
    00578             lpTarget->Release();
    00579             DDSURFACEDESC2 ddsd;
    00580             ddsd.dwSize = sizeof(DDSURFACEDESC2);
    00581             lpTarget->GetSurfaceDesc(&ddsd);
    00582             DWORD stencil =  ddsd.ddpfPixelFormat.dwStencilBitDepth;
    00583             if(stencil > 0)
    00584             {
    00585                 mCapabilities->setCapability(RSC_HWSTENCIL);
    00586                 mCapabilities->setStencilBufferBitDepth(stencil);
    00587                 if ((mD3DDeviceDesc.dwStencilCaps & D3DSTENCILCAPS_INCR) &&
    00588                     (mD3DDeviceDesc.dwStencilCaps & D3DSTENCILCAPS_DECR))
    00589                     mCapabilities->setCapability(RSC_STENCIL_WRAP);
    00590             }
    00591
    00592             // Anisotropy?
    00593             if (mD3DDeviceDesc.dwMaxAnisotropy > 1)
    00594                 mCapabilities->setCapability(RSC_ANISOTROPY);
    00595             // Blending between stages supported
    00596             mCapabilities->setCapability(RSC_BLENDING);
    00597             // Cubemapping
    00598             if (mD3DDeviceDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP)
    00599                 mCapabilities->setCapability(RSC_CUBEMAPPING);
    00600
    00601             // DOT3
    00602             if (mD3DDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
    00603                 mCapabilities->setCapability(RSC_DOT3);
    00604
    00605             // Set the number of texture units based on details from current device
    00606             mCapabilities->setNumTextureUnits(mD3DDeviceDesc.wMaxSimultaneousTextures);
    00607
    00608             mCapabilities->log(LogManager::getSingleton().getDefaultLog());
    00609
    00610             firstWindow = false;
    00611         }
    00612
    00613         OgreUnguardRet( win );
    00614     }
    00615
    00616     RenderTexture * D3DRenderSystem::createRenderTexture( const String & name, unsigned int width, unsigned int height )
    00617     {
    00618         RenderTexture * rt = new D3D7RenderTexture( name, width, height );
    00619         attachRenderTarget( *rt );
    00620         return rt;
    00621     }
    00622
    00623     //-----------------------------------------------------------------------
    00624     // Low-level overridden members
    00625     //-----------------------------------------------------------------------
    00626     //---------------------------------------------------------------------
    00627     void D3DRenderSystem::_useLights(const LightList& lights, unsigned short limit)
    00628     {
    00629         LightList::const_iterator i, iend;
    00630         iend = lights.end();
    00631         unsigned short num = 0;
    00632         for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
    00633         {
    00634             setD3DLight(num, *i);
    00635         }
    00636         // Disable extra lights
    00637         for (; num < mCurrentLights; ++num)
    00638         {
    00639             setD3DLight(num, NULL);
    00640         }
    00641         mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
    00642
    00643     }
    00644     //-----------------------------------------------------------------------
    00645     void D3DRenderSystem::setD3DLight(size_t index, Light* lt)
    00646     {
    00647         // Add to D3D
    00648         HRESULT hr;
    00649         D3DLIGHT7 d3dLight;
    00650
    00651         if (!lt)
    00652         {
    00653             hr = mlpD3DDevice->LightEnable(index, FALSE);
    00654             if (FAILED(hr))
    00655                 Except(hr, "Unable to disable light.", "D3DRenderSystem::setD3DLight");
    00656         }
    00657         else
    00658         {
    00659             switch (lt->getType())
    00660             {
    00661             case Light::LT_POINT:
    00662                 d3dLight.dltType = D3DLIGHT_POINT;
    00663                 break;
    00664             case Light::LT_DIRECTIONAL:
    00665                 d3dLight.dltType = D3DLIGHT_DIRECTIONAL;
    00666                 break;
    00667             case Light::LT_SPOTLIGHT:
    00668                 d3dLight.dltType = D3DLIGHT_SPOT;
    00669                 d3dLight.dvFalloff = lt->getSpotlightFalloff();
    00670                 d3dLight.dvTheta = lt->getSpotlightInnerAngle().valueRadians();
    00671                 d3dLight.dvPhi = lt->getSpotlightOuterAngle().valueRadians();
    00672                 break;
    00673             }
    00674
    00675             // Colours
    00676             ColourValue col;
    00677             col = lt->getDiffuseColour();
    00678             d3dLight.dcvDiffuse.r = col.r;
    00679             d3dLight.dcvDiffuse.g = col.g;
    00680             d3dLight.dcvDiffuse.b = col.b;
    00681             d3dLight.dcvDiffuse.a = col.a;
    00682
    00683             col = lt->getSpecularColour();
    00684             d3dLight.dcvSpecular.r = col.r;
    00685             d3dLight.dcvSpecular.g = col.g;
    00686             d3dLight.dcvSpecular.b = col.b;
    00687             d3dLight.dcvSpecular.a = col.a;
    00688
    00689             // Never use ambient for a movable light
    00690             d3dLight.dcvAmbient.r = 0.0;
    00691             d3dLight.dcvAmbient.g = 0.0;
    00692             d3dLight.dcvAmbient.b = 0.0;
    00693             d3dLight.dcvAmbient.a = 0.0;
    00694
    00695             // Position (Irrelevant for directional)
    00696             Vector3 vec;
    00697             if (lt->getType() != Light::LT_DIRECTIONAL)
    00698             {
    00699                 vec = lt->getDerivedPosition();
    00700
    00701                 d3dLight.dvPosition.x = vec.x;
    00702                 d3dLight.dvPosition.y = vec.y;
    00703                 d3dLight.dvPosition.z = vec.z;
    00704             }
    00705             // Direction (Irrelevant for point lights)
    00706             if (lt->getType() != Light::LT_POINT)
    00707             {
    00708                 vec = lt->getDerivedDirection();
    00709                 d3dLight.dvDirection.x = vec.x;
    00710                 d3dLight.dvDirection.y = vec.y;
    00711                 d3dLight.dvDirection.z = vec.z;
    00712             }
    00713             // Attenuation parameters
    00714             d3dLight.dvRange = lt->getAttenuationRange();
    00715             d3dLight.dvAttenuation0 = lt->getAttenuationConstant();
    00716             d3dLight.dvAttenuation1 = lt->getAttenuationLinear();
    00717             d3dLight.dvAttenuation2 = lt->getAttenuationQuadric();
    00718
    00719
    00720
    00721             // Set light state
    00722             hr = mlpD3DDevice->SetLight(index, &d3dLight);
    00723
    00724             if (FAILED(hr))
    00725                 Except(hr, "Unable to set light details", "D3DRenderSystem::setD3DLight");
    00726
    00727             hr = mlpD3DDevice->LightEnable(index, TRUE);
    00728             if (FAILED(hr))
    00729                 Except(hr, "Unable to enable light.", "D3DRenderSystem::setD3DLight");
    00730         }
    00731
    00732
    00733     }
    00734     //-----------------------------------------------------------------------
    00735     D3DMATRIX D3DRenderSystem::makeD3DMatrix(const Matrix4& mat)
    00736     {
    00737         // Transpose matrix
    00738         // D3D uses row vectors i.e. V*M
    00739         // Ogre, OpenGL and everything else uses coloumn vectors i.e. M*V
    00740         D3DMATRIX d3dMat;
    00741
    00742         d3dMat.m[0][0] = mat[0][0];
    00743         d3dMat.m[0][1] = mat[1][0];
    00744         d3dMat.m[0][2] = mat[2][0];
    00745         d3dMat.m[0][3] = mat[3][0];
    00746
    00747         d3dMat.m[1][0] = mat[0][1];
    00748         d3dMat.m[1][1] = mat[1][1];
    00749         d3dMat.m[1][2] = mat[2][1];
    00750         d3dMat.m[1][3] = mat[3][1];
    00751
    00752         d3dMat.m[2][0] = mat[0][2];
    00753         d3dMat.m[2][1] = mat[1][2];
    00754         d3dMat.m[2][2] = mat[2][2];
    00755         d3dMat.m[2][3] = mat[3][2];
    00756
    00757         d3dMat.m[3][0] = mat[0][3];
    00758         d3dMat.m[3][1] = mat[1][3];
    00759         d3dMat.m[3][2] = mat[2][3];
    00760         d3dMat.m[3][3] = mat[3][3];
    00761
    00762         return d3dMat;
    00763     }
    00764
    00765     Matrix4 D3DRenderSystem::convertD3DMatrix(const D3DMATRIX& d3dmat)
    00766     {
    00767         // The reverse of makeD3DMatrix
    00768         // Transpose matrix
    00769         // D3D uses row vectors i.e. V*M
    00770         // Ogre, OpenGL and everything else uses coloumn vectors i.e. M*V
    00771         Matrix4 mat;
    00772         for (unsigned row = 0; row < 4; ++row)
    00773             for (unsigned col = 0; col < 4; ++col)
    00774                 mat[col][row] = d3dmat.m[row][col];
    00775
    00776         return mat;
    00777
    00778
    00779     }
    00780     //-----------------------------------------------------------------------
    00781     void D3DRenderSystem::_setWorldMatrix(const Matrix4 &m)
    00782     {
    00783         D3DMATRIX d3dmat;
    00784
    00785         d3dmat = makeD3DMatrix(m);
    00786
    00787         HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &d3dmat);
    00788
    00789         if (FAILED(hr))
    00790             Except(hr, "Cannot set D3D world matrix",
    00791             "D3DRenderSystem::_setWorldMatrix");
    00792     }
    00793
    00794     //-----------------------------------------------------------------------
    00795     void D3DRenderSystem::_setViewMatrix(const Matrix4 &m)
    00796     {
    00797         // save latest view matrix
    00798         mViewMatrix = m;
    00799         mViewMatrix[2][0] = -mViewMatrix[2][0];
    00800         mViewMatrix[2][1] = -mViewMatrix[2][1];
    00801         mViewMatrix[2][2] = -mViewMatrix[2][2];
    00802         mViewMatrix[2][3] = -mViewMatrix[2][3];
    00803
    00804         D3DMATRIX d3dmat = makeD3DMatrix(mViewMatrix);
    00805
    00806         HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &d3dmat);
    00807
    00808         if (FAILED(hr))
    00809             Except(hr, "Cannot set D3D view matrix",
    00810             "D3DRenderSystem::_setViewMatrix");
    00811
    00812     }
    00813     //-----------------------------------------------------------------------
    00814     void D3DRenderSystem::_setProjectionMatrix(const Matrix4 &m)
    00815     {
    00816         D3DMATRIX d3dmat = makeD3DMatrix(m);
    00817
    00818         if( mActiveRenderTarget->requiresTextureFlipping() )
    00819         {
    00820             d3dmat._22 = - d3dmat._22;
    00821         }
    00822
    00823         HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &d3dmat);
    00824
    00825         if (FAILED(hr))
    00826             Except(hr, "Cannot set D3D projection matrix",
    00827             "D3DRenderSystem::_setProjectionMatrix");
    00828     }
    00829
    00830
    00831     //-----------------------------------------------------------------------
    00832     void D3DRenderSystem::_setSurfaceParams(const ColourValue &ambient,
    00833         const ColourValue &diffuse, const ColourValue &specular,
    00834         const ColourValue &emissive, const Real shininess)
    00835     {
    00836         // Remember last call
    00837         static ColourValue lastAmbient = ColourValue::Black;
    00838         static ColourValue lastDiffuse = ColourValue::Black;
    00839         static ColourValue lastSpecular = ColourValue::Black;
    00840         static ColourValue lastEmissive = ColourValue::Black;
    00841         static Real lastShininess = 0.0;
    00842
    00843         // Only update if changed
    00844         if (ambient != lastAmbient || diffuse != lastDiffuse ||
    00845             specular != lastSpecular || emissive != lastEmissive ||
    00846             shininess != lastShininess)
    00847         {
    00848
    00849             // Convert to D3D
    00850             D3DMATERIAL7 d3dMat;
    00851
    00852             d3dMat.dcvDiffuse.r = diffuse.r;
    00853             d3dMat.dcvDiffuse.g = diffuse.g;
    00854             d3dMat.dcvDiffuse.b = diffuse.b;
    00855             d3dMat.dcvDiffuse.a = diffuse.a;
    00856
    00857             d3dMat.dcvAmbient.r = ambient.r;
    00858             d3dMat.dcvAmbient.g = ambient.g;
    00859             d3dMat.dcvAmbient.b = ambient.b;
    00860             d3dMat.dcvAmbient.a = ambient.a;
    00861
    00862             d3dMat.dcvSpecular.r = specular.r;
    00863             d3dMat.dcvSpecular.g = specular.g;
    00864             d3dMat.dcvSpecular.b = specular.b;
    00865             d3dMat.dcvSpecular.a = specular.a;
    00866
    00867             d3dMat.dcvEmissive.r = emissive.r;
    00868             d3dMat.dcvEmissive.g = emissive.g;
    00869             d3dMat.dcvEmissive.b = emissive.b;
    00870             d3dMat.dcvEmissive.a = emissive.a;
    00871
    00872             d3dMat.dvPower = shininess;
    00873
    00874             HRESULT hr = mlpD3DDevice->SetMaterial(&d3dMat);
    00875             if (FAILED(hr))
    00876                 Except(hr, "Error setting D3D material.", "D3DRenderSystem::_setSurfaceParams");
    00877
    00878         }
    00879     }
    00880     //-----------------------------------------------------------------------
    00881     void D3DRenderSystem::_setTexture(size_t stage, bool enabled, const String &texname)
    00882     {
    00883         HRESULT hr;
    00884         D3DTexture* dt = static_cast< D3DTexture* >(TextureManager::getSingleton().getByName(texname));
    00885         if (enabled && dt)
    00886         {
    00887             LPDIRECTDRAWSURFACE7 pTex = dt->getDDSurface();
    00888             if (pTex != mTexStageDesc[stage].pTex)
    00889             {
    00890                 hr = mlpD3DDevice->SetTexture(stage, pTex );
    00891                 if (FAILED(hr))
    00892                     Except(hr, "Unable to set texture in D3D.", "D3DRenderSystem::_setTexture");
    00893
    00894                 // set stage desc.
    00895                 mTexStageDesc[stage].texType = _ogreTexTypeToD3DTexType(dt->getTextureType());
    00896                 mTexStageDesc[stage].pTex = pTex;
    00897             }
    00898         }
    00899         else
    00900         {
    00901             hr = mlpD3DDevice->SetTexture(stage, 0);
    00902             if (FAILED(hr))
    00903                 Except(hr, "Unable to disable texture in D3D.", "D3DRenderSystem::_setTexture");
    00904             hr = __SetTextureStageState( stage, D3DTSS_COLOROP, D3DTOP_DISABLE );
    00905             if (FAILED(hr))
    00906                 Except(hr, "Unable to disable texture in D3D.", "D3DRenderSystem::_setTexture");
    00907
    00908             // set stage desc. to defaults
    00909             mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
    00910             mTexStageDesc[stage].coordIndex = 0;
    00911             mTexStageDesc[stage].texType = D3D_TEX_TYPE_NORMAL;
    00912             mTexStageDesc[stage].pTex = NULL;
    00913         }
    00914     }
    00915     //---------------------------------------------------------------------
    00916     DWORD getD3DTexCalc(TexCoordCalcMethod tcc)
    00917     {
    00918         switch (tcc)
    00919         {
    00920         case TEXCALC_NONE:
    00921             return 0;
    00922         case TEXCALC_ENVIRONMENT_MAP:
    00923             // D3D7 does not support spherical reflection
    00924             return D3DTSS_TCI_CAMERASPACENORMAL;
    00925         case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
    00926             return D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR;
    00927         case TEXCALC_ENVIRONMENT_MAP_PLANAR:
    00928         case TEXCALC_PROJECTIVE_TEXTURE:
    00929             return D3DTSS_TCI_CAMERASPACEPOSITION;
    00930         case TEXCALC_ENVIRONMENT_MAP_NORMAL:
    00931             return D3DTSS_TCI_CAMERASPACENORMAL;
    00932         }
    00933     }
    00934     //-----------------------------------------------------------------------
    00935     void D3DRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m,
    00936         const Frustum* frustum)
    00937     {
    00938         HRESULT hr = S_OK;
    00939         // record the stage state
    00940         mTexStageDesc[stage].autoTexCoordType = m;
    00941         mTexStageDesc[stage].frustum = frustum;
    00942
    00943         hr = __SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX,
    00944             getD3DTexCalc(m) | mTexStageDesc[stage].coordIndex);
    00945         if( FAILED( hr ) )
    00946             Except( hr, "Error setting texture coord calculation", "D3DRenderSystem::_setTextureCoordCalculation" );
    00947
    00948     }
    00949     //-----------------------------------------------------------------------
    00950     void D3DRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xForm)
    00951     {
    00952         HRESULT hr;
    00953         D3DMATRIX d3dMat; // the matrix we'll maybe apply
    00954         Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format
    00955
    00956
    00957         /* If envmap is applied, since D3D7 doesn't support spheremap,
    00958         then we have to use texture transform to make the camera space normal
    00959         reference the envmap properly. This isn't exactly the same as spheremap
    00960         (it looks nasty on flat areas because the camera space normals are the same)
    00961         but it's the best approximation we have in the absence of a proper spheremap */
    00962         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP)
    00963         {
    00964             // concatenate with the xForm
    00965             newMat = newMat.concatenate(Matrix4::CLIPSPACE2DTOIMAGESPACE);
    00966         }
    00967
    00968         // If this is a cubic reflection, we need to modify using the view matrix
    00969         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION)
    00970         {
    00971             D3DMATRIX viewMatrix;
    00972
    00973             // Get view matrix
    00974             mlpD3DDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, &viewMatrix);
    00975             // Get transposed 3x3, ie since D3D is transposed just copy
    00976             // We want to transpose since that will invert an orthonormal matrix ie rotation
    00977             Matrix4 ogreViewTransposed;
    00978             ogreViewTransposed[0][0] = viewMatrix.m[0][0];
    00979             ogreViewTransposed[0][1] = viewMatrix.m[0][1];
    00980             ogreViewTransposed[0][2] = viewMatrix.m[0][2];
    00981             ogreViewTransposed[0][3] = 0.0f;
    00982
    00983             ogreViewTransposed[1][0] = viewMatrix.m[1][0];
    00984             ogreViewTransposed[1][1] = viewMatrix.m[1][1];
    00985             ogreViewTransposed[1][2] = viewMatrix.m[1][2];
    00986             ogreViewTransposed[1][3] = 0.0f;
    00987
    00988             ogreViewTransposed[2][0] = viewMatrix.m[2][0];
    00989             ogreViewTransposed[2][1] = viewMatrix.m[2][1];
    00990             ogreViewTransposed[2][2] = viewMatrix.m[2][2];
    00991             ogreViewTransposed[2][3] = 0.0f;
    00992
    00993             ogreViewTransposed[3][0] = 0.0f;
    00994             ogreViewTransposed[3][1] = 0.0f;
    00995             ogreViewTransposed[3][2] = 0.0f;
    00996             ogreViewTransposed[3][3] = 1.0f;
    00997
    00998             newMat = newMat.concatenate(ogreViewTransposed);
    00999         }
    01000
    01001         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
    01002         {
    01003             // Derive camera space to projector space transform
    01004             // To do this, we need to undo the camera view matrix, then
    01005             // apply the projector view & projection matrices
    01006             newMat = mViewMatrix.inverse() * newMat;
    01007             newMat = mTexStageDesc[stage].frustum->getViewMatrix() * newMat;
    01008             newMat = mTexStageDesc[stage].frustum->getProjectionMatrix() * newMat;
    01009             if (mTexStageDesc[stage].frustum->getProjectionType() == PT_PERSPECTIVE)
    01010             {
    01011                 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * newMat;
    01012             }
    01013             else
    01014             {
    01015                 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO * newMat;
    01016             }
    01017
    01018         }
    01019
    01020         // convert our matrix to D3D format
    01021         d3dMat = makeD3DMatrix(newMat);
    01022
    01023         // need this if texture is a cube map, to invert D3D's z coord
    01024         if (mTexStageDesc[stage].autoTexCoordType != TEXCALC_NONE)
    01025         {
    01026             d3dMat._13 = -d3dMat._13;
    01027             d3dMat._23 = -d3dMat._23;
    01028             d3dMat._33 = -d3dMat._33;
    01029             d3dMat._43 = -d3dMat._43;
    01030         }
    01031
    01032         // set the matrix if it's not the identity
    01033         if (!(newMat == Matrix4::IDENTITY))
    01034         {
    01035             // tell D3D the dimension of tex. coord.
    01036             int texCoordDim;
    01037             if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
    01038             {
    01039                 texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT3;
    01040             }
    01041             else
    01042             {
    01043                 switch (mTexStageDesc[stage].texType)
    01044                 {
    01045                 case D3D_TEX_TYPE_NORMAL:
    01046                     texCoordDim = D3DTTFF_COUNT2;
    01047                     break;
    01048                 case D3D_TEX_TYPE_CUBE:
    01049                 case D3D_TEX_TYPE_VOLUME:
    01050                     texCoordDim = D3DTTFF_COUNT3;
    01051                 }
    01052             }
    01053
    01054             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim );
    01055             if (FAILED(hr))
    01056                 Except( hr, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" );
    01057
    01058             hr = mlpD3DDevice->SetTransform(
    01059                 (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + stage), &d3dMat );
    01060             if (FAILED(hr))
    01061                 Except( hr, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
    01062         }
    01063         else
    01064         {
    01065             // disable all of this
    01066             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
    01067             if( FAILED( hr ) )
    01068                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
    01069
    01070             // set the identity matrix
    01071             D3DUtil_SetIdentityMatrix( d3dMat );
    01072             hr = mlpD3DDevice->SetTransform(
    01073                 (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + stage), &d3dMat );
    01074             if( FAILED( hr ) )
    01075                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
    01076         }
    01077     }
    01078     //---------------------------------------------------------------------
    01079     void D3DRenderSystem::_setTextureCoordSet( size_t stage, size_t index )
    01080     {
    01081         HRESULT hr;
    01082         hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX,
    01083             getD3DTexCalc(mTexStageDesc[stage].autoTexCoordType) | index );
    01084         if( FAILED( hr ) )
    01085             Except( hr, "Unable to set texture coord. set index", "D3DRenderSystem::_setTextureCoordSet" );
    01086         // Record settings
    01087         mTexStageDesc[stage].coordIndex = index;
    01088     }
    01089     //-----------------------------------------------------------------------
    01090     void D3DRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm)
    01091     {
    01092         HRESULT hr;
    01093         D3DTEXTURESTAGESTATETYPE tss;
    01094         DWORD value;
    01095
    01096         if (bm.blendType == LBT_COLOUR)
    01097         {
    01098             tss = D3DTSS_COLOROP;
    01099         }
    01100         else if (bm.blendType == LBT_ALPHA)
    01101         {
    01102             tss= D3DTSS_ALPHAOP;
    01103         }
    01104
    01105         switch (bm.operation)
    01106         {
    01107         case LBX_SOURCE1:
    01108             value = D3DTOP_SELECTARG1;
    01109             break;
    01110         case LBX_SOURCE2:
    01111             value = D3DTOP_SELECTARG2;
    01112             break;
    01113         case LBX_MODULATE:
    01114             value = D3DTOP_MODULATE;
    01115             break;
    01116         case LBX_MODULATE_X2:
    01117             value = D3DTOP_MODULATE2X;
    01118             break;
    01119         case LBX_MODULATE_X4:
    01120             value = D3DTOP_MODULATE4X;
    01121             break;
    01122         case LBX_ADD:
    01123             value = D3DTOP_ADD;
    01124             break;
    01125         case LBX_ADD_SIGNED:
    01126             value = D3DTOP_ADDSIGNED;
    01127             break;
    01128         case LBX_ADD_SMOOTH:
    01129             value = D3DTOP_ADDSMOOTH;
    01130             break;
    01131         case LBX_SUBTRACT:
    01132             value = D3DTOP_SUBTRACT;
    01133             break;
    01134         case LBX_BLEND_DIFFUSE_ALPHA:
    01135             value = D3DTOP_BLENDDIFFUSEALPHA;
    01136             break;
    01137         case LBX_BLEND_TEXTURE_ALPHA:
    01138             value = D3DTOP_BLENDTEXTUREALPHA;
    01139             break;
    01140         case LBX_BLEND_CURRENT_ALPHA:
    01141             value = D3DTOP_BLENDCURRENTALPHA;
    01142             break;
    01143         case LBX_BLEND_MANUAL:
    01144             value = D3DTOP_BLENDFACTORALPHA;
    01145             // Set factor in render state
    01146             hr = __SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR,
    01147                 D3DRGBA(0,0,0,bm.factor));
    01148             break;
    01149         case LBX_DOTPRODUCT:
    01150             if (mD3DDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
    01151                 value = D3DTOP_DOTPRODUCT3;
    01152             else
    01153                 value = D3DTOP_MODULATE;
    01154             break;
    01155         }
    01156
    01157         // Make call to set operation
    01158         hr = __SetTextureStageState(stage, tss, value);
    01159
    01160         // Now set up sources
    01161         D3DCOLOR manualD3D;
    01162         if (bm.blendType == LBT_COLOUR)
    01163         {
    01164             tss = D3DTSS_COLORARG1;
    01165             manualD3D = D3DRGBA(bm.colourArg1.r,bm.colourArg1.g,bm.colourArg1.b,1.0);
    01166         }
    01167         else if (bm.blendType == LBT_ALPHA)
    01168         {
    01169             tss = D3DTSS_ALPHAARG1;
    01170             manualD3D = D3DRGBA(0,0,0,bm.alphaArg1);
    01171         }
    01172         LayerBlendSource bs = bm.source1;
    01173         for (int i = 0; i < 2; ++i)
    01174         {
    01175             switch (bs)
    01176             {
    01177             case LBS_CURRENT:
    01178                 value = D3DTA_CURRENT;
    01179                 break;
    01180             case LBS_TEXTURE:
    01181                 value = D3DTA_TEXTURE;
    01182                 break;
    01183             case LBS_DIFFUSE:
    01184                 value = D3DTA_DIFFUSE;
    01185                 break;
    01186             case LBS_SPECULAR:
    01187                 value = D3DTA_SPECULAR;
    01188                 break;
    01189             case LBS_MANUAL:
    01190                 value = D3DTA_TFACTOR;
    01191                 // Set factor in render state
    01192                 hr = __SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR,    manualD3D);
    01193                 break;
    01194             }
    01195
    01196             // Set source
    01197             hr = __SetTextureStageState(stage, tss, value);
    01198
    01199             // Source2
    01200             bs = bm.source2;
    01201             if (bm.blendType == LBT_COLOUR)
    01202             {
    01203                 tss = D3DTSS_COLORARG2;
    01204                 manualD3D = D3DRGBA(bm.colourArg2.r,bm.colourArg2.g,bm.colourArg2.b,1.0);
    01205             }
    01206             else if (bm.blendType == LBT_ALPHA)
    01207             {
    01208                 tss = D3DTSS_ALPHAARG2;
    01209                 manualD3D = D3DRGBA(0,0,0,bm.alphaArg2);
    01210             }
    01211         }
    01212     }
    01213     //-----------------------------------------------------------------------
    01214     void D3DRenderSystem::_setTextureAddressingMode(size_t stage, TextureUnitState::TextureAddressingMode tam)
    01215     {
    01216         HRESULT hr;
    01217         D3DTEXTUREADDRESS d3dType;
    01218
    01219         switch(tam)
    01220         {
    01221         case TextureUnitState::TAM_WRAP:
    01222             d3dType = D3DTADDRESS_WRAP;
    01223             break;
    01224         case TextureUnitState::TAM_MIRROR:
    01225             d3dType = D3DTADDRESS_MIRROR;
    01226             break;
    01227         case TextureUnitState::TAM_CLAMP:
    01228             d3dType = D3DTADDRESS_CLAMP;
    01229             break;
    01230         }
    01231
    01232
    01233         hr = __SetTextureStageState(stage, D3DTSS_ADDRESS, d3dType);
    01234     }
    01235     //-----------------------------------------------------------------------
    01236     void D3DRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
    01237     {
    01238         HRESULT hr;
    01239         D3DBLEND d3dSrcBlend, d3dDestBlend;
    01240
    01241         D3DBLEND* pBlend = &d3dSrcBlend;
    01242         SceneBlendFactor ogreBlend = sourceFactor;
    01243
    01244         for (int i = 0 ; i < 2; ++i)
    01245         {
    01246             switch(ogreBlend)
    01247             {
    01248             case SBF_ONE:
    01249                 *pBlend = D3DBLEND_ONE;
    01250                 break;
    01251             case SBF_ZERO:
    01252                 *pBlend = D3DBLEND_ZERO;
    01253                 break;
    01254             case SBF_DEST_COLOUR:
    01255                 *pBlend = D3DBLEND_DESTCOLOR;
    01256                 break;
    01257             case SBF_SOURCE_COLOUR:
    01258                 *pBlend = D3DBLEND_SRCCOLOR;
    01259                 break;
    01260             case SBF_ONE_MINUS_DEST_COLOUR:
    01261                 *pBlend = D3DBLEND_INVDESTCOLOR;
    01262                 break;
    01263             case SBF_ONE_MINUS_SOURCE_COLOUR:
    01264                 *pBlend = D3DBLEND_INVSRCCOLOR;
    01265                 break;
    01266             case SBF_DEST_ALPHA:
    01267                 *pBlend = D3DBLEND_DESTALPHA;
    01268                 break;
    01269             case SBF_SOURCE_ALPHA:
    01270                 *pBlend = D3DBLEND_SRCALPHA;
    01271                 break;
    01272             case SBF_ONE_MINUS_DEST_ALPHA:
    01273                 *pBlend = D3DBLEND_INVDESTALPHA;
    01274                 break;
    01275             case SBF_ONE_MINUS_SOURCE_ALPHA:
    01276                 *pBlend = D3DBLEND_INVSRCALPHA;
    01277                 break;
    01278             }
    01279             ogreBlend = destFactor;
    01280             pBlend = &d3dDestBlend;
    01281
    01282         }
    01283
    01284         hr = __SetRenderState(D3DRENDERSTATE_SRCBLEND, d3dSrcBlend);
    01285
    01286         hr = __SetRenderState(D3DRENDERSTATE_DESTBLEND, d3dDestBlend);
    01287
    01288         // Save last scene blend, because colour write off is simulated
    01289         // through scene blend
    01290         mSavedDestFactor = destFactor;
    01291         mSavedSrcFactor = sourceFactor;
    01292
    01293
    01294     }
    01295     //-----------------------------------------------------------------------
    01296     void D3DRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value)
    01297     {
    01298         HRESULT hr;
    01299         if (func != CMPF_ALWAYS_PASS)
    01300         {
    01301             if( FAILED( hr = __SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE,  TRUE ) ) )
    01302                 Except( hr, "Failed to enable alpha testing",
    01303                 "D3DRenderSystem::_setAlphaRejectSettings" );
    01304         }
    01305         else
    01306         {
    01307             if( FAILED( hr = __SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE,  FALSE ) ) )
    01308                 Except( hr, "Failed to disable alpha testing",
    01309                 "D3DRenderSystem::_setAlphaRejectSettings" );
    01310         }
    01311
    01312         // Set always just be sure
    01313         hr = __SetRenderState(D3DRENDERSTATE_ALPHAFUNC,
    01314             convertCompareFunction(func));
    01315
    01316         hr = __SetRenderState(D3DRENDERSTATE_ALPHAREF, value);
    01317     }
    01318     //-----------------------------------------------------------------------
    01319     void D3DRenderSystem::_setViewport(Viewport *vp)
    01320     {
    01321         // Check if viewport is different
    01322         if (vp != mActiveViewport || vp->_isUpdated())
    01323         {
    01324             mActiveViewport = vp;
    01325             mActiveRenderTarget = vp->getTarget();
    01326             // Ok, it's different. Time to set render target (maybe)
    01327             //  and viewport params.
    01328             D3DVIEWPORT7 d3dvp;
    01329             HRESULT hr;
    01330
    01331             // Set render target
    01332             // TODO - maybe only set when required?
    01333             RenderTarget* target;
    01334             target = vp->getTarget();
    01335             // Get DD Back buffer
    01336             LPDIRECTDRAWSURFACE7 pBack;
    01337             target->getCustomAttribute("DDBACKBUFFER", &pBack);
    01338
    01339             hr = mlpD3DDevice->SetRenderTarget( pBack, 0 );
    01340
    01341             _setCullingMode( mCullingMode );
    01342
    01343             // Set viewport dimensions
    01344             d3dvp.dwX = vp->getActualLeft();
    01345             d3dvp.dwY = vp->getActualTop();
    01346             d3dvp.dwWidth = vp->getActualWidth();
    01347             d3dvp.dwHeight = vp->getActualHeight();
    01348
    01349             // Z-values from 0.0 to 1.0 (TODO - standardise with OpenGL?)
    01350             d3dvp.dvMinZ = 0.0f;
    01351             d3dvp.dvMaxZ = 1.0f;
    01352
    01353             hr = mlpD3DDevice->SetViewport(&d3dvp);
    01354
    01355             if (FAILED(hr))
    01356                 Except(hr, "Error setting D3D viewport.",
    01357                 "D3DRenderSystem::_setViewport");
    01358
    01359             vp->_clearUpdatedFlag();
    01360
    01361         }
    01362     }
    01363
    01364     //-----------------------------------------------------------------------
    01365     void D3DRenderSystem::_beginFrame(void)
    01366     {
    01367         OgreGuard( "D3DRenderSystem::_beginFrame" );
    01368
    01369         HRESULT hr;
    01370
    01371         if (!mActiveViewport)
    01372             Except(999, "Cannot begin frame - no viewport selected.",
    01373             "D3DRenderSystem::_beginFrame");
    01374
    01375         // Clear the viewport if required
    01376         if (mActiveViewport->getClearEveryFrame())
    01377         {
    01378             clearFrameBuffer(FBT_COLOUR | FBT_DEPTH,
    01379                 mActiveViewport->getBackgroundColour());
    01380         }
    01381
    01382         hr = mlpD3DDevice->BeginScene();
    01383         if (FAILED(hr))
    01384             Except(hr, "Error beginning frame.",
    01385             "D3DRenderSystem::_beginFrame");
    01386
    01387         // Moved here from _render, no point checking every rendering call
    01388         static bool firstTime = true;
    01389         if (firstTime)
    01390         {
    01391             // First-time setup
    01392             // Set up some defaults
    01393
    01394             // Allow alpha blending
    01395             hr = __SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
    01396             if (FAILED(hr))
    01397                 Except(hr, "Error enabling alpha blending option.",
    01398                 "D3DRenderSystem::_beginFrame");
    01399
    01400             // Allow specular effects
    01401             hr = __SetRenderState(D3DRENDERSTATE_SPECULARENABLE, TRUE);
    01402             if (FAILED(hr))
    01403                 Except(hr, "Error enabling specular option.",
    01404                 "D3DRenderSystem::_beginFrame");
    01405
    01406             firstTime = false;
    01407         }
    01408
    01409         OgreUnguard();
    01410     }
    01411
    01412     //-----------------------------------------------------------------------
    01413     void D3DRenderSystem::_render(const RenderOperation& op)
    01414     {
    01415         OgreGuard( "D3DRenderSystem::_render" );
    01416         HRESULT hr;
    01417
    01418         // Exit immediately if there is nothing to render
    01419         // Passing 0 arguments causes problems for Direct3D
    01420         if (op.vertexData->vertexCount == 0 ||
    01421             (op.useIndexes && op.indexData->indexCount == 0))
    01422             return;
    01423
    01424         // call superclass
    01425         RenderSystem::_render(op);
    01426         // Set up vertex flags
    01427         DWORD d3dVertexFormat = 0;
    01428         unsigned int numTexCoords = 0;
    01429
    01430         // Assume no more than 10 buffers!
    01431         static unsigned char* pBufPtrs[10];
    01432
    01433         // Lock all the buffers first
    01434         // They're system memory buffers anyway
    01435         const VertexBufferBinding::VertexBufferBindingMap binds =
    01436             op.vertexData->vertexBufferBinding->getBindings();
    01437         VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi, bindend;
    01438         bindend = binds.end();
    01439         for (bindi = binds.begin(); bindi != bindend; ++bindi)
    01440         {
    01441             // lock from vertex start only
    01442             pBufPtrs[bindi->first] = static_cast<unsigned char*>(
    01443                 bindi->second->lock(
    01444                     op.vertexData->vertexStart * bindi->second->getVertexSize(),
    01445                     op.vertexData->vertexCount * bindi->second->getVertexSize(),
    01446                     HardwareBuffer::HBL_READ_ONLY)
    01447                     );
    01448
    01449         }
    01450
    01451         // Determine vertex format
    01452
    01453         // Struct for data pointers
    01454         D3DDRAWPRIMITIVESTRIDEDDATA strideData;
    01455
    01456         // Iterate over elements
    01457         VertexDeclaration::VertexElementList::const_iterator elemi, elemend;
    01458         const VertexDeclaration::VertexElementList elems =
    01459             op.vertexData->vertexDeclaration->getElements();
    01460         elemend = elems.end();
    01461         for (elemi = elems.begin(); elemi != elemend; ++elemi)
    01462         {
    01463             // Get a few basic details
    01464             const VertexElement& elem = *elemi;
    01465             unsigned short source = elem.getSource();
    01466             size_t vertexSize = op.vertexData->vertexDeclaration->getVertexSize(source);
    01467             size_t offset = elem.getOffset();
    01468             // semantic-specific stuff
    01469             switch (elem.getSemantic())
    01470             {
    01471             case VES_POSITION:
    01472                 d3dVertexFormat |= D3DFVF_XYZ; // Untransformed
    01473                 strideData.position.lpvData = pBufPtrs[source] + offset;
    01474                 strideData.position.dwStride = static_cast<DWORD>(vertexSize);
    01475                 // Set up pointer
    01476                 break;
    01477             case VES_NORMAL:
    01478                 d3dVertexFormat |= D3DFVF_NORMAL;
    01479                 strideData.normal.lpvData = pBufPtrs[source] + offset;
    01480                 strideData.normal.dwStride = static_cast<DWORD>(vertexSize);
    01481                 break;
    01482             case VES_DIFFUSE:
    01483                 d3dVertexFormat |= D3DFVF_DIFFUSE;
    01484                 strideData.diffuse.lpvData = pBufPtrs[source] + offset;
    01485                 strideData.diffuse.dwStride = static_cast<DWORD>(vertexSize);
    01486                 break;
    01487             case VES_SPECULAR:
    01488                 d3dVertexFormat |= D3DFVF_SPECULAR;
    01489                 strideData.specular.lpvData = pBufPtrs[source] + offset;
    01490                 strideData.specular.dwStride = static_cast<DWORD>(vertexSize);
    01491                 break;
    01492             case VES_TEXTURE_COORDINATES:
    01493                 // texcoords must go in order
    01494                 if (elem.getIndex() != numTexCoords)
    01495                 {
    01496                     Except(Exception::ERR_INVALIDPARAMS, "Invalid vertex format, texture coordinates"
    01497                         " must be in order wih no gaps.", "D3DRenderSystem::_render");
    01498                 }
    01499                 // Don't add D3DFVF_TEXn flag here, wait until we know how many total
    01500                 // However, specify size
    01501                 switch (elem.getType())
    01502                 {
    01503                 case VET_FLOAT1:
    01504                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE1(numTexCoords);
    01505                     break;
    01506                 case VET_FLOAT2:
    01507                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE2(numTexCoords);
    01508                     break;
    01509                 case VET_FLOAT3:
    01510                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE3(numTexCoords);
    01511                     break;
    01512                 case VET_FLOAT4:
    01513                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE4(numTexCoords);
    01514                     break;
    01515                 }
    01516
    01517                 strideData.textureCoords[numTexCoords].lpvData = pBufPtrs[source] + offset;
    01518                 strideData.textureCoords[numTexCoords].dwStride = static_cast<DWORD>(vertexSize);
    01519
    01520                 // Increment number of coords
    01521                 ++numTexCoords;
    01522             }
    01523
    01524         }
    01525         // Add combined texture flag
    01526         switch(numTexCoords)
    01527         {
    01528             case 0:
    01529                 // do nothing
    01530                 break;
    01531             case 1:
    01532                 d3dVertexFormat |= D3DFVF_TEX1;
    01533                 break;
    01534             case 2:
    01535                 d3dVertexFormat |= D3DFVF_TEX2;
    01536                 break;
    01537             case 3:
    01538                 d3dVertexFormat |= D3DFVF_TEX3;
    01539                 break;
    01540             case 4:
    01541                 d3dVertexFormat |= D3DFVF_TEX4;
    01542                 break;
    01543             case 5:
    01544                 d3dVertexFormat |= D3DFVF_TEX5;
    01545                 break;
    01546             case 6:
    01547                 d3dVertexFormat |= D3DFVF_TEX6;
    01548                 break;
    01549             case 7:
    01550                 d3dVertexFormat |= D3DFVF_TEX7;
    01551                 break;
    01552             case 8:
    01553                 d3dVertexFormat |= D3DFVF_TEX8;
    01554                 break;
    01555         }
    01556
    01557         // Determine rendering operation
    01558         D3DPRIMITIVETYPE primType;
    01559         switch (op.operationType)
    01560         {
    01561         case RenderOperation::OT_POINT_LIST:
    01562             primType = D3DPT_POINTLIST;
    01563             break;
    01564         case RenderOperation::OT_LINE_LIST:
    01565             primType = D3DPT_LINELIST;
    01566             break;
    01567         case RenderOperation::OT_LINE_STRIP:
    01568             primType = D3DPT_LINESTRIP;
    01569             break;
    01570         case RenderOperation::OT_TRIANGLE_LIST:
    01571             primType = D3DPT_TRIANGLELIST;
    01572             break;
    01573         case RenderOperation::OT_TRIANGLE_STRIP:
    01574             primType = D3DPT_TRIANGLESTRIP;
    01575             break;
    01576         case RenderOperation::OT_TRIANGLE_FAN:
    01577             primType = D3DPT_TRIANGLEFAN;
    01578             break;
    01579         }
    01580
    01581
    01582         if (op.useIndexes)
    01583         {
    01584             // Get pointer to index buffer
    01585             // D3D7 only allows 16-bit indexes, this is enforced in buffer manager
    01586             unsigned short* pIdx = static_cast<unsigned short*>(
    01587                 op.indexData->indexBuffer->lock(
    01588                     op.indexData->indexStart,
    01589                     op.indexData->indexCount * sizeof(unsigned short),
    01590                     HardwareBuffer::HBL_READ_ONLY) );
    01591
    01592             hr = mlpD3DDevice->DrawIndexedPrimitiveStrided(primType,
    01593                 d3dVertexFormat,
    01594                 &strideData,
    01595                 static_cast<DWORD>(op.vertexData->vertexCount),
    01596                 pIdx,
    01597                 static_cast<DWORD>(op.indexData->indexCount)
    01598                 , 0);
    01599         }
    01600         else
    01601         {
    01602             hr = mlpD3DDevice->DrawPrimitiveStrided(primType,
    01603                 d3dVertexFormat,
    01604                 &strideData,
    01605                 static_cast<DWORD>(op.vertexData->vertexCount),
    01606                 0);
    01607         }
    01608
    01609         // unlock buffers
    01610         for (bindi = binds.begin(); bindi != bindend; ++bindi)
    01611         {
    01612             bindi->second->unlock();
    01613         }
    01614
    01615         if (FAILED(hr))
    01616         {
    01617             char szBuffer[512];
    01618             D3DXGetErrorString( hr, 512, szBuffer );
    01619             Except( hr, szBuffer, "D3DRenderSystem::_render");
    01620         }
    01621
    01622
    01623
    01624
    01625         OgreUnguard();
    01626     }
    01627
    01628     //-----------------------------------------------------------------------
    01629     void D3DRenderSystem::_endFrame(void)
    01630     {
    01631         OgreGuard( "D3DRenderSystem::_endFrame" );
    01632
    01633         HRESULT hr;
    01634         hr = mlpD3DDevice->EndScene();
    01635
    01636         if (FAILED(hr))
    01637             Except(hr, "Error ending frame.",
    01638             "D3DRenderSystem::_endFrame");
    01639
    01640         OgreUnguard();
    01641     }
    01642
    01643     //-----------------------------------------------------------------------
    01644     void D3DRenderSystem::_setCullingMode(CullingMode mode)
    01645     {
    01646         HRESULT hr;
    01647         DWORD d3dMode;
    01648
    01649         mCullingMode = mode;
    01650
    01651         if (mode == CULL_NONE)
    01652         {
    01653             d3dMode = D3DCULL_NONE;
    01654         }
    01655         else if( mode == CULL_CLOCKWISE )
    01656         {
    01657             if( (mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
    01658                 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding))
    01659                 d3dMode = D3DCULL_CCW;
    01660             else
    01661                 d3dMode = D3DCULL_CW;
    01662         }
    01663         else if (mode == CULL_ANTICLOCKWISE)
    01664         {
    01665             if( (mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
    01666                 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding))
    01667                 d3dMode = D3DCULL_CW;
    01668             else
    01669                 d3dMode = D3DCULL_CCW;
    01670         }
    01671
    01672         hr = __SetRenderState(D3DRENDERSTATE_CULLMODE, d3dMode);
    01673         if (FAILED(hr))
    01674             Except(hr, "Unable to set D3D culling mode.",
    01675             "D3DRenderSystem::_setCullingMode");
    01676
    01677     }
    01678
    01679     //-----------------------------------------------------------------------
    01680     void D3DRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
    01681     {
    01682         _setDepthBufferCheckEnabled(depthTest);
    01683         _setDepthBufferWriteEnabled(depthWrite);
    01684         _setDepthBufferFunction(depthFunction);
    01685
    01686     }
    01687     //-----------------------------------------------------------------------
    01688     void D3DRenderSystem::_setDepthBufferCheckEnabled(bool enabled)
    01689     {
    01690         HRESULT hr;
    01691
    01692         if (enabled)
    01693         {
    01694             // Use w-buffer if available and enabled
    01695             if (mWBuffer && mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_WBUFFER)
    01696                 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_USEW);
    01697             else
    01698                 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
    01699             if (FAILED(hr))
    01700                 Except(hr, "Error setting depth buffer test state.",
    01701                 "D3DRenderSystem::_setDepthBufferCheckEnabled");
    01702         }
    01703         else
    01704         {
    01705             hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
    01706             if (FAILED(hr))
    01707                 Except(hr, "Error setting depth buffer test state.",
    01708                 "D3DRenderSystem::_setDepthBufferCheckEnabled");
    01709         }
    01710     }
    01711     //-----------------------------------------------------------------------
    01712     void D3DRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
    01713     {
    01714         HRESULT hr;
    01715
    01716         hr = __SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, enabled);
    01717         if (FAILED(hr))
    01718             Except(hr, "Error setting depth buffer write state.",
    01719             "D3DRenderSystem::_setDepthBufferWriteEnabled");
    01720     }
    01721     //-----------------------------------------------------------------------
    01722     void D3DRenderSystem::_setDepthBufferFunction(CompareFunction func)
    01723     {
    01724         HRESULT hr = __SetRenderState(D3DRENDERSTATE_ZFUNC,
    01725             convertCompareFunction(func));
    01726         if (FAILED(hr))
    01727             Except(hr, "Error setting depth buffer test function.",
    01728             "D3DRenderSystem::_setDepthBufferFunction");
    01729     }
    01730     //-----------------------------------------------------------------------
    01731     void D3DRenderSystem::_setDepthBias(ushort bias)
    01732     {
    01733         HRESULT hr = __SetRenderState(D3DRENDERSTATE_ZBIAS,
    01734             bias);
    01735         if (FAILED(hr))
    01736             Except(hr, "Error setting depth bias.",
    01737             "D3DRenderSystem::_setDepthBias");
    01738     }
    01739     //-----------------------------------------------------------------------
    01740     String D3DRenderSystem::getErrorDescription(long errCode) const
    01741     {
    01742         char* errDesc;
    01743         DWORD i;
    01744
    01745         errDesc = new char[255];
    01746         // Try windows errors first
    01747         i = FormatMessage(
    01748             FORMAT_MESSAGE_FROM_HMODULE |
    01749             FORMAT_MESSAGE_FROM_SYSTEM |
    01750             FORMAT_MESSAGE_IGNORE_INSERTS,
    01751             NULL,
    01752             DDERR_SURFACELOST,
    01753             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    01754             (LPTSTR) errDesc,
    01755             255,
    01756             NULL
    01757             );
    01758
    01759
    01760         if (i == 0)
    01761         {
    01762             // Not found in windows message descriptions
    01763             switch (errCode)
    01764             {
    01765             case DD_OK:
    01766                 strcpy(errDesc, "DD_OK: The request completed successfully.");
    01767                 break;
    01768             case DDERR_ALREADYINITIALIZED:
    01769                 strcpy(errDesc, "DDERR_ALREADYINITIALIZED: The object has already been initialized.");
    01770                 break;
    01771             case DDERR_BLTFASTCANTCLIP :
    01772                 strcpy(errDesc, "DDERR_BLTFASTCANTCLIP: A DirectDrawClipper object is attached to a source surface that has passed into a call to the IDirectDrawSurface7::BltFast method.");
    01773                 break;
    01774             case DDERR_CANNOTATTACHSURFACE:
    01775                 strcpy(errDesc, "DDERR_CANNOTATTACHSURFACE: A surface cannot be attached to another requested surface.");
    01776                 break;
    01777             case DDERR_CANNOTDETACHSURFACE:
    01778                 strcpy(errDesc, "DDERR_CANNOTATTACHSURFACE: A surface cannot be detached from another requested surface.");
    01779                 break;
    01780             case DDERR_CANTCREATEDC:
    01781                 strcpy(errDesc, "DDERR_CANTCREATEDC: Windows can not create any more device contexts (DCs), or a DC was requested for a palette-indexed surface when the surface had no palette and the display mode was not palette-indexed.");
    01782                 break;
    01783             case DDERR_CANTDUPLICATE:
    01784                 strcpy(errDesc, "DDERR_CANTDUPLICATE: Primary and 3-D surfaces, or surfaces that are implicitly created, cannot be duplicated.");
    01785                 break;
    01786             case DDERR_CANTLOCKSURFACE:
    01787                 strcpy(errDesc, "DDERR_CANTLOCKSURFACE: Access to this surface is refused because an attempt was made to lock the primary surface without DCI support.");
    01788                 break;
    01789             case DDERR_CANTPAGELOCK:
    01790                 strcpy(errDesc, "DDERR_CANTPAGELOCK: An attempt to page lock a surface failed. Page lock will not work on a display-memory surface or an emulated primary surface.");
    01791                 break;
    01792             case DDERR_CANTPAGEUNLOCK:
    01793                 strcpy(errDesc, "DDERR_CANTPAGEUNLOCK: An attempt to page unlock a surface failed. Page unlock will not work on a display-memory surface or an emulated primary surface.");
    01794                 break;
    01795             case DDERR_CLIPPERISUSINGHWND:
    01796                 strcpy(errDesc, "DDERR_CLIPPERISUSINGHWND: An attempt was made to set a clip list for a DirectDrawClipper object that is already monitoring a window handle.");
    01797                 break;
    01798             case DDERR_COLORKEYNOTSET:
    01799                 strcpy(errDesc, "DDERR_COLORKEYNOTSET: No source color key is specified for this operation.");
    01800                 break;
    01801             case DDERR_CURRENTLYNOTAVAIL:
    01802                 strcpy(errDesc, "DDERR_CURRENTLYNOTAVAIL: No support is currently available.");
    01803                 break;
    01804             case DDERR_DCALREADYCREATED:
    01805                 strcpy(errDesc, "DDERR_DCALREADYCREATED: A device context (DC) has already been returned for this surface. Only one DC can be retrieved for each surface.");
    01806                 break;
    01807             case DDERR_DEVICEDOESNTOWNSURFACE:
    01808                 strcpy(errDesc, "DDERR_DEVICEDOESNTOWNSURFACE: Surfaces created by one DirectDraw device cannot be used directly by another DirectDraw device.");
    01809                 break;
    01810             case DDERR_DIRECTDRAWALREADYCREATED:
    01811                 strcpy(errDesc, "DDERR_DIRECTDRAWALREADYCREATED: A DirectDraw object representing this driver has already been created for this process.");
    01812                 break;
    01813             case DDERR_EXCEPTION:
    01814                 strcpy(errDesc, "DDERR_EXCEPTION: An exception was encountered while performing the requested operation.");
    01815                 break;
    01816             case DDERR_EXCLUSIVEMODEALREADYSET:
    01817                 strcpy(errDesc, "DDERR_EXCLUSIVEMODEALREADYSET: An attempt was made to set the cooperative level when it was already set to exclusive.");
    01818                 break;
    01819             case DDERR_EXPIRED:
    01820                 strcpy(errDesc, "DDERR_EXPIRED: The data has expired and is therefore no longer valid.");
    01821                 break;
    01822             case DDERR_GENERIC:
    01823                 strcpy(errDesc, "DDERR_GENERIC: There is an undefined error condition.");
    01824                 break;
    01825             case DDERR_HEIGHTALIGN:
    01826                 strcpy(errDesc, "DDERR_HEIGHTALIGN: The height of the provided rectangle is not a multiple of the required alignment.");
    01827                 break;
    01828             case DDERR_HWNDALREADYSET:
    01829                 strcpy(errDesc, "DDERR_HWNDALREADYSET: The DirectDraw cooperative level window handle has already been set. It cannot be reset while the process has surfaces or palettes created.");
    01830                 break;
    01831             case DDERR_HWNDSUBCLASSED:
    01832                 strcpy(errDesc, "DDERR_HWNDSUBCLASSED: DirectDraw is prevented from restoring state because the DirectDraw cooperative level window handle has been subclassed.");
    01833                 break;
    01834             case DDERR_IMPLICITLYCREATED:
    01835                 strcpy(errDesc, "DDERR_IMPLICITLYCREATED: The surface cannot be restored because it is an implicitly created surface.");
    01836                 break;
    01837             case DDERR_INCOMPATIBLEPRIMARY:
    01838                 strcpy(errDesc, "DDERR_INCOMPATIBLEPRIMARY: The primary surface creation request does not match with the existing primary surface.");
    01839                 break;
    01840             case DDERR_INVALIDCAPS:
    01841                 strcpy(errDesc, "DDERR_INVALIDCAPS: One or more of the capability bits passed to the callback function are incorrect.");
    01842                 break;
    01843             case DDERR_INVALIDCLIPLIST:
    01844                 strcpy(errDesc, "DDERR_INVALIDCLIPLIST: DirectDraw does not support the provided clip list.");
    01845                 break;
    01846             case DDERR_INVALIDDIRECTDRAWGUID:
    01847                 strcpy(errDesc, "DDERR_INVALIDDIRECTDRAWGUID: The globally unique identifier (GUID) passed to the DirectDrawCreate function is not a valid DirectDraw driver identifier.");
    01848                 break;
    01849             case DDERR_INVALIDMODE:
    01850                 strcpy(errDesc, "DDERR_INVALIDMODE: DirectDraw does not support the requested mode.");
    01851                 break;
    01852             case DDERR_INVALIDOBJECT:
    01853                 strcpy(errDesc, "DDERR_INVALIDOBJECT: DirectDraw received a pointer that was an invalid DirectDraw object.");
    01854                 break;
    01855             case DDERR_INVALIDPARAMS:
    01856                 strcpy(errDesc, "DDERR_INVALIDPARAMS: One or more of the parameters passed to the method are incorrect.");
    01857                 break;
    01858             case DDERR_INVALIDPIXELFORMAT:
    01859                 strcpy(errDesc, "DDERR_INVALIDPIXELFORMAT: The pixel format was invalid as specified.");
    01860                 break;
    01861             case DDERR_INVALIDPOSITION:
    01862                 strcpy(errDesc, "DDERR_INVALIDPOSITION: The position of the overlay on the destination is no longer legal.");
    01863                 break;
    01864             case DDERR_INVALIDRECT:
    01865                 strcpy(errDesc, "DDERR_INVALIDRECT: The provided rectangle was invalid.");
    01866                 break;
    01867             case DDERR_INVALIDSTREAM:
    01868                 strcpy(errDesc, "DDERR_INVALIDSTREAM: The specified stream contains invalid data.");
    01869                 break;
    01870             case DDERR_INVALIDSURFACETYPE:
    01871                 strcpy(errDesc, "DDERR_INVALIDSURFACETYPE: The requested operation could not be performed because the surface was of the wrong type.");
    01872                 break;
    01873             case DDERR_LOCKEDSURFACES:
    01874                 strcpy(errDesc, "DDERR_LOCKEDSURFACES: One or more surfaces are locked, causing the failure of the requested operation.");
    01875                 break;
    01876             case DDERR_MOREDATA:
    01877                 strcpy(errDesc, "DDERR_MOREDATA: There is more data available than the specified buffer size can hold.");
    01878                 break;
    01879             case DDERR_NO3D:
    01880                 strcpy(errDesc, "DDERR_NO3D: No 3-D hardware or emulation is present.");
    01881                 break;
    01882             case DDERR_NOALPHAHW:
    01883                 strcpy(errDesc, "DDERR_NOALPHAHW: No alpha acceleration hardware is present or available, causing the failure of the requested operation.");
    01884                 break;
    01885             case DDERR_NOBLTHW:
    01886                 strcpy(errDesc, "DDERR_NOBLTHW: No blitter hardware is present.");
    01887                 break;
    01888             case DDERR_NOCLIPLIST:
    01889                 strcpy(errDesc, "DDERR_NOCLIPLIST: No clip list is available.");
    01890                 break;
    01891             case DDERR_NOCLIPPERATTACHED:
    01892                 strcpy(errDesc, "DDERR_NOCLIPPERATTACHED: No DirectDrawClipper object is attached to the surface object.");
    01893                 break;
    01894             case DDERR_NOCOLORCONVHW:
    01895                 strcpy(errDesc, "DDERR_NOCOLORCONVHW: The operation cannot be carried out because no color-conversion hardware is present or available.");
    01896                 break;
    01897             case DDERR_NOCOLORKEY:
    01898                 strcpy(errDesc, "DDERR_NOCOLORKEY: The surface does not currently have a color key.");
    01899                 break;
    01900             case DDERR_NOCOLORKEYHW:
    01901                 strcpy(errDesc, "DDERR_NOCOLORKEYHW: The operation cannot be carried out because there is no hardware support for the destination color key.");
    01902                 break;
    01903             case DDERR_NOCOOPERATIVELEVELSET:
    01904                 strcpy(errDesc, "DDERR_NOCOOPERATIVELEVELSET: A create function is called without the IDirectDraw7::SetCooperativeLevel method being called.");
    01905                 break;
    01906             case DDERR_NODC:
    01907                 strcpy(errDesc, "DDERR_NODC: No DC has ever been created for this surface.");
    01908                 break;
    01909             case DDERR_NODDROPSHW:
    01910                 strcpy(errDesc, "DDERR_NODDROPSHW: No DirectDraw raster operation (ROP) hardware is available.");
    01911                 break;
    01912             case DDERR_NODIRECTDRAWHW:
    01913                 strcpy(errDesc, "DDERR_NODIRECTDRAWHW: Hardware-only DirectDraw object creation is not possible; the driver does not support any hardware.");
    01914                 break;
    01915             case DDERR_NODIRECTDRAWSUPPORT:
    01916                 strcpy(errDesc, "DDERR_NODIRECTDRAWSUPPORT: DirectDraw support is not possible with the current display driver.");
    01917                 break;
    01918             case DDERR_NOEMULATION:
    01919                 strcpy(errDesc, "DDERR_NOEMULATION: Software emulation is not available.");
    01920                 break;
    01921             case DDERR_NOEXCLUSIVEMODE:
    01922                 strcpy(errDesc, "DDERR_NOEXCLUSIVEMODE: The operation requires the application to have exclusive mode, but the application does not have exclusive mode.");
    01923                 break;
    01924             case DDERR_NOFLIPHW:
    01925                 strcpy(errDesc, "DDERR_NOFLIPHW: Flipping visible surfaces is not supported.");
    01926                 break;
    01927             case DDERR_NOFOCUSWINDOW:
    01928                 strcpy(errDesc, "DDERR_NOFOCUSWINDOW: An attempt was made to create or set a device window without first setting the focus window.");
    01929                 break;
    01930             case DDERR_NOGDI:
    01931                 strcpy(errDesc, "DDERR_NOGDI: No GDI is present.");
    01932                 break;
    01933             case DDERR_NOHWND:
    01934                 strcpy(errDesc, "DDERR_NOHWND: Clipper notification requires a window handle, or no window handle has been previously set as the cooperative level window handle.");
    01935                 break;
    01936             case DDERR_NOMIPMAPHW:
    01937                 strcpy(errDesc, "DDERR_NOMIPMAPHW: The operation cannot be carried out because no mipmap capable texture mapping hardware is present or available.");
    01938                 break;
    01939             case DDERR_NOMIRRORHW:
    01940                 strcpy(errDesc, "DDERR_NOMIRRORHW: The operation cannot be carried out because no mirroring hardware is present or available.");
    01941                 break;
    01942             case DDERR_NONONLOCALVIDMEM:
    01943                 strcpy(errDesc, "DDERR_NONONLOCALVIDMEM: An attempt was made to allocate non-local video memory from a device that does not support non-local video memory.");
    01944                 break;
    01945             case DDERR_NOOPTIMIZEHW:
    01946                 strcpy(errDesc, "DDERR_NOOPTIMIZEHW: The device does not support optimized surfaces.");
    01947                 break;
    01948             case DDERR_NOOVERLAYDEST:
    01949                 strcpy(errDesc, "DDERR_NOOVERLAYDEST: The IDirectDrawSurface4::GetOverlayPosition method is called on an overlay that the IDirectDrawSurface7::UpdateOverlay method has not been called on to establish a destination.");
    01950                 break;
    01951             case DDERR_NOOVERLAYHW:
    01952                 strcpy(errDesc, "DDERR_NOOVERLAYHW: The operation cannot be carried out because no overlay hardware is present or available.");
    01953                 break;
    01954             case DDERR_NOPALETTEATTACHED:
    01955                 strcpy(errDesc, "DDERR_NOPALETTEATTACHED: No palette object is attached to this surface.");
    01956                 break;
    01957             case DDERR_NOPALETTEHW:
    01958                 strcpy(errDesc, "DDERR_NOPALETTEHW: There is no hardware support for 16- or 256-color palettes.");
    01959                 break;
    01960             case DDERR_NORASTEROPHW:
    01961                 strcpy(errDesc, "DDERR_NORASTEROPHW: The operation cannot be carried out because no appropriate raster operation hardware is present or available.");
    01962                 break;
    01963             case DDERR_NOROTATIONHW:
    01964                 strcpy(errDesc, "DDERR_NOROTATIONHW: The operation cannot be carried out because no rotation hardware is present or available.");
    01965                 break;
    01966             case DDERR_NOSTRETCHHW:
    01967                 strcpy(errDesc, "DDERR_NOSTRETCHHW: The operation cannot be carried out because there is no hardware support for stretching.");
    01968                 break;
    01969             case DDERR_NOT4BITCOLOR:
    01970                 strcpy(errDesc, "DDERR_NOT4BITCOLOR: The DirectDrawSurface object is not using a 4-bit color palette and the requested operation requires a 4-bit color palette.");
    01971                 break;
    01972             case DDERR_NOT4BITCOLORINDEX:
    01973                 strcpy(errDesc, "DDERR_NOT4BITCOLORINDEX: The DirectDrawSurface object is not using a 4-bit color index palette and the requested operation requires a 4-bit color index palette.");
    01974                 break;
    01975             case DDERR_NOT8BITCOLOR:
    01976                 strcpy(errDesc, "DDERR_NOT8BITCOLOR: The DirectDrawSurface object is not using an 8-bit color palette and the requested operation requires an 8-bit color palette.");
    01977                 break;
    01978             case DDERR_NOTAOVERLAYSURFACE:
    01979                 strcpy(errDesc, "DDERR_NOTAOVERLAYSURFACE: An overlay component is called for a non-overlay surface.");
    01980                 break;
    01981             case DDERR_NOTEXTUREHW:
    01982                 strcpy(errDesc, "DDERR_NOTEXTUREHW: The operation cannot be carried out because no texture-mapping hardware is present or available.");
    01983                 break;
    01984             case DDERR_NOTFLIPPABLE:
    01985                 strcpy(errDesc, "DDERR_NOTFLIPPABLE: An attempt has been made to flip a surface that cannot be flipped.");
    01986                 break;
    01987             case DDERR_NOTFOUND:
    01988                 strcpy(errDesc, "DDERR_NOTFOUND: The requested item was not found.");
    01989                 break;
    01990             case DDERR_NOTINITIALIZED:
    01991                 strcpy(errDesc, "DDERR_NOTINITIALIZED: An attempt was made to call an interface method of a DirectDraw object created by CoCreateInstance before the object was initialized.");
    01992                 break;
    01993             case DDERR_NOTLOADED:
    01994                 strcpy(errDesc, "DDERR_NOTLOADED: The surface is an optimized surface, but it has not yet been allocated any memory.");
    01995                 break;
    01996             case DDERR_NOTLOCKED:
    01997                 strcpy(errDesc, "DDERR_NOTLOCKED: An attempt is made to unlock a surface that was not locked.");
    01998                 break;
    01999             case DDERR_NOTPAGELOCKED:
    02000                 strcpy(errDesc, "DDERR_NOTPAGELOCKED: An attempt is made to page unlock a surface with no outstanding page locks.");
    02001                 break;
    02002             case DDERR_NOTPALETTIZED:
    02003                 strcpy(errDesc, "DDERR_NOTPALETTIZED: The surface being used is not a palette-based surface.");
    02004                 break;
    02005             case DDERR_NOVSYNCHW:
    02006                 strcpy(errDesc, "DDERR_NOVSYNCHW: The operation cannot be carried out because there is no hardware support for vertical blank synchronized operations.");
    02007                 break;
    02008             case DDERR_NOZBUFFERHW:
    02009                 strcpy(errDesc, "DDERR_NOZBUFFERHW: The operation to create a z-buffer in display memory or to perform a blit using a z-buffer cannot be carried out because there is no hardware support for z-buffers.");
    02010                 break;
    02011             case DDERR_NOZOVERLAYHW:
    02012                 strcpy(errDesc, "DDERR_NOZOVERLAYHW: The overlay surfaces cannot be z-layered based on the z-order because the hardware does not support z-ordering of overlays.");
    02013                 break;
    02014             case DDERR_OUTOFCAPS:
    02015                 strcpy(errDesc, "DDERR_OUTOFCAPS: The hardware needed for the requested operation has already been allocated.");
    02016                 break;
    02017             case DDERR_OUTOFMEMORY:
    02018                 strcpy(errDesc, "DDERR_OUTOFMEMORY: DirectDraw does not have enough memory to perform the operation.");
    02019                 break;
    02020             case DDERR_OUTOFVIDEOMEMORY:
    02021                 strcpy(errDesc, "DDERR_OUTOFVIDEOMEMORY: DirectDraw does not have enough display memory to perform the operation.");
    02022                 break;
    02023             case DDERR_OVERLAPPINGRECTS:
    02024                 strcpy(errDesc, "DDERR_OVERLAPPINGRECTS: Operation could not be carried out because the source and destination rectangles are on the same surface and overlap each other.");
    02025                 break;
    02026             case DDERR_OVERLAYCANTCLIP:
    02027                 strcpy(errDesc, "DDERR_OVERLAYCANTCLIP: The hardware does not support clipped overlays.");
    02028                 break;
    02029             case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
    02030                 strcpy(errDesc, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE: An attempt was made to have more than one color key active on an overlay.");
    02031                 break;
    02032             case DDERR_OVERLAYNOTVISIBLE:
    02033                 strcpy(errDesc, "DDERR_OVERLAYNOTVISIBLE: The IDirectDrawSurface7::GetOverlayPosition method is called on a hidden overlay.");
    02034                 break;
    02035             case DDERR_PALETTEBUSY:
    02036                 strcpy(errDesc, "DDERR_PALETTEBUSY: Access to this palette is refused because the palette is locked by another thread.");
    02037                 break;
    02038             case DDERR_PRIMARYSURFACEALREADYEXISTS:
    02039                 strcpy(errDesc, "DDERR_PRIMARYSURFACEALREADYEXISTS: This process has already created a primary surface.");
    02040                 break;
    02041             case DDERR_REGIONTOOSMALL:
    02042                 strcpy(errDesc, "DDERR_REGIONTOOSMALL: The region passed to the IDirectDrawClipper::GetClipList method is too small.");
    02043                 break;
    02044             case DDERR_SURFACEALREADYATTACHED:
    02045                 strcpy(errDesc, "DDERR_SURFACEALREADYATTACHED: An attempt was made to attach a surface to another surface to which it is already attached.");
    02046                 break;
    02047             case DDERR_SURFACEALREADYDEPENDENT:
    02048                 strcpy(errDesc, "DDERR_SURFACEALREADYDEPENDENT: An attempt was made to make a surface a dependency of another surface to which it is already dependent.");
    02049                 break;
    02050             case DDERR_SURFACEBUSY:
    02051                 strcpy(errDesc, "DDERR_SURFACEBUSY: Access to the surface is refused because the surface is locked by another thread.");
    02052                 break;
    02053             case DDERR_SURFACEISOBSCURED:
    02054                 strcpy(errDesc, "DDERR_SURFACEISOBSCURED: Access to the surface is refused because the surface is obscured.");
    02055                 break;
    02056             case DDERR_SURFACELOST:
    02057                 strcpy(errDesc, "DDERR_SURFACELOST: Access to the surface is refused because the surface memory is gone. Call the IDirectDrawSurface7::Restore method on this surface to restore the memory associated with it.");
    02058                 break;
    02059             case DDERR_SURFACENOTATTACHED:
    02060                 strcpy(errDesc, "DDERR_SURFACENOTATTACHED: The requested surface is not attached.");
    02061                 break;
    02062             case DDERR_TOOBIGHEIGHT:
    02063                 strcpy(errDesc, "DDERR_TOOBIGHEIGHT: The height requested by DirectDraw is too large.");
    02064                 break;
    02065             case DDERR_TOOBIGSIZE:
    02066                 strcpy(errDesc, "DDERR_TOOBIGSIZE: The size requested by DirectDraw is too large. However, the individual height and width are valid sizes.");
    02067                 break;
    02068             case DDERR_TOOBIGWIDTH:
    02069                 strcpy(errDesc, "DDERR_TOOBIGWIDTH: The width requested by DirectDraw is too large.");
    02070                 break;
    02071             case DDERR_UNSUPPORTED:
    02072                 strcpy(errDesc, "DDERR_UNSUPPORTED: The operation is not supported.");
    02073                 break;
    02074             case DDERR_UNSUPPORTEDFORMAT:
    02075                 strcpy(errDesc, "DDERR_UNSUPPORTEDFORMAT: The FourCC format requested is not supported by DirectDraw.");
    02076                 break;
    02077             case DDERR_UNSUPPORTEDMASK:
    02078                 strcpy(errDesc, "DDERR_UNSUPPORTEDMASK: The bitmask in the pixel format requested is not supported by DirectDraw.");
    02079                 break;
    02080             case DDERR_UNSUPPORTEDMODE:
    02081                 strcpy(errDesc, "DDERR_UNSUPPORTEDMODE: The display is currently in an unsupported mode.");
    02082                 break;
    02083             case DDERR_VERTICALBLANKINPROGRESS:
    02084                 strcpy(errDesc, "DDERR_VERTICALBLANKINPROGRESS: A vertical blank is in progress.");
    02085                 break;
    02086             case DDERR_VIDEONOTACTIVE:
    02087                 strcpy(errDesc, "DDERR_VIDEONOTACTIVE: The video port is not active.");
    02088                 break;
    02089             case DDERR_WASSTILLDRAWING:
    02090                 strcpy(errDesc, "DDERR_WASSTILLDRAWING: The previous blit operation that is transferring information to or from this surface is incomplete.");
    02091                 break;
    02092             case DDERR_WRONGMODE:
    02093                 strcpy(errDesc, "DDERR_WRONGMODE: This surface cannot be restored because it was created in a different mode.");
    02094                 break;
    02095             case DDERR_XALIGN:
    02096                 strcpy(errDesc, "DDERR_XALIGN: The provided rectangle was not horizontally aligned on a required boundary.");
    02097                 break;
    02098             default:
    02099                 strcpy(errDesc, "Unknown error code.");
    02100             }
    02101         }
    02102         return errDesc;
    02103     }
    02104
    02105     /*
    02106     D3D_OK
    02107     D3DERR_BADMAJORVERSION
    02108     D3DERR_BADMINORVERSION
    02109     D3DERR_COLORKEYATTACHED
    02110     D3DERR_CONFLICTINGTEXTUREFILTER
    02111     D3DERR_CONFLICTINGTEXTUREPALETTE
    02112     D3DERR_CONFLICTINGRENDERSTATE
    02113     D3DERR_DEVICEAGGREGATED (new for DirectX 5.0)
    02114     D3DERR_EXECUTE_CLIPPED_FAILED
    02115     D3DERR_EXECUTE_CREATE_FAILED
    02116     D3DERR_EXECUTE_DESTROY_FAILED
    02117     D3DERR_EXECUTE_FAILED
    02118     D3DERR_EXECUTE_LOCK_FAILED
    02119     D3DERR_EXECUTE_LOCKED
    02120     D3DERR_EXECUTE_NOT_LOCKED
    02121     D3DERR_EXECUTE_UNLOCK_FAILED
    02122     D3DERR_INITFAILED (new for DirectX 5.0)
    02123     D3DERR_INBEGIN (new for DirectX 5.0)
    02124     D3DERR_INVALID_DEVICE (new for DirectX 5.0)
    02125     D3DERR_INVALIDCURRENTVIEWPORT (new for DirectX 5.0)
    02126     D3DERR_INVALIDMATRIX
    02127     D3DERR_INVALIDPALETTE(new for DirectX 5.0)
    02128     D3DERR_INVALIDPRIMITIVETYPE (new for DirectX 5.0)
    02129     D3DERR_INVALIDRAMPTEXTURE (new for DirectX 5.0)
    02130     D3DERR_INVALIDVERTEXFORMAT (new for DirectX 6.0)
    02131     D3DERR_INVALIDVERTEXTYPE (new for DirectX 5.0)
    02132     D3DERR_LIGHT_SET_FAILED
    02133     D3DERR_LIGHTHASVIEWPORT (new for DirectX 5.0)
    02134     D3DERR_LIGHTNOTINTHISVIEWPORT (new for DirectX 5.0)
    02135     D3DERR_MATERIAL_CREATE_FAILED
    02136     D3DERR_MATERIAL_DESTROY_FAILED
    02137     D3DERR_MATERIAL_GETDATA_FAILED
    02138     D3DERR_MATERIAL_SETDATA_FAILED
    02139     D3DERR_MATRIX_CREATE_FAILED
    02140     D3DERR_MATRIX_DESTROY_FAILED
    02141     D3DERR_MATRIX_GETDATA_FAILED
    02142     D3DERR_MATRIX_SETDATA_FAILED
    02143     D3DERR_NOCURRENTVIEWPORT (new for DirectX 5.0)
    02144     D3DERR_NOTINBEGIN (new for DirectX 5.0)
    02145     D3DERR_NOVIEWPORTS (new for DirectX 5.0)
    02146     D3DERR_SCENE_BEGIN_FAILED
    02147     D3DERR_SCENE_END_FAILED
    02148     D3DERR_SCENE_IN_SCENE
    02149     D3DERR_SCENE_NOT_IN_SCENE
    02150     D3DERR_SETVIEWPORTDATA_FAILED
    02151     D3DERR_STENCILBUFFER_NOTPRESENT
    02152     D3DERR_SURFACENOTINVIDMEM (new for DirectX 5.0)
    02153     D3DERR_TEXTURE_BADSIZE (new for DirectX 5.0)
    02154     D3DERR_TEXTURE_CREATE_FAILED
    02155     D3DERR_TEXTURE_DESTROY_FAILED
    02156     D3DERR_TEXTURE_GETSURF_FAILED
    02157     D3DERR_TEXTURE_LOAD_FAILED
    02158     D3DERR_TEXTURE_LOCK_FAILED
    02159     D3DERR_TEXTURE_LOCKED
    02160     D3DERR_TEXTURE_NO_SUPPORT
    02161     D3DERR_TEXTURE_NOT_LOCKED
    02162     D3DERR_TEXTURE_SWAP_FAILED
    02163     D3DERR_TEXTURE_UNLOCK_FAILED
    02164     D3DERR_TOOMANYOPERATIONS
    02165     D3DERR_TOOMANYPRIMITIVES
    02166     D3DERR_UNSUPPORTEDALPHAARG
    02167     D3DERR_UNSUPPORTEDALPHAOPERATION
    02168     D3DERR_UNSUPPORTEDCOLORARG
    02169     D3DERR_UNSUPPORTEDCOLOROPERATION
    02170     D3DERR_UNSUPPORTEDFACTORVALUE
    02171     D3DERR_UNSUPPORTEDTEXTUREFILTER
    02172     D3DERR_VBUF_CREATE_FAILED
    02173     D3DERR_VERTEXBUFFERLOCKED
    02174     D3DERR_VERTEXBUFFEROPTIMIZED
    02175     D3DERR_VIEWPORTDATANOTSET (new for DirectX 5.0)
    02176     D3DERR_VIEWPORTHASNODEVICE (new for DirectX 5.0)
    02177     D3DERR_WRONGTEXTUREFORMAT
    02178     D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY (new for DirectX 5.0)
    02179     D3DERR_ZBUFF_NEEDS_VIDEOMEMORY (new for DirectX 5.0)
    02180     D3DERR_ZBUFFER_NOTPRESENT
    02181     */
    02182
    02183     //-----------------------------------------------------------------------
    02184     DDDriverList* D3DRenderSystem::getDirectDrawDrivers(void)
    02185     {
    02186         if (!mDriverList)
    02187         {
    02188             mDriverList = new DDDriverList;
    02189         }
    02190
    02191         return mDriverList;
    02192     }
    02193     //-----------------------------------------------------------------------
    02194     void D3DRenderSystem::setLightingEnabled(bool enabled)
    02195     {
    02196         // Call D3D
    02197         HRESULT hr = __SetRenderState(D3DRENDERSTATE_LIGHTING, enabled);
    02198         if (FAILED(hr))
    02199             Except(hr, "Error lighting status.", "D3DRenderSystem::setLightingEnabled");
    02200     }
    02201     //-----------------------------------------------------------------------
    02202     void D3DRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
    02203     {
    02204         HRESULT hr;
    02205
    02206         D3DRENDERSTATETYPE fogType, fogTypeNot;
    02207
    02208         if (mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)
    02209         {
    02210             fogType = D3DRENDERSTATE_FOGTABLEMODE;
    02211             fogTypeNot = D3DRENDERSTATE_FOGVERTEXMODE;
    02212         }
    02213         else
    02214         {
    02215             fogType = D3DRENDERSTATE_FOGVERTEXMODE;
    02216             fogTypeNot = D3DRENDERSTATE_FOGTABLEMODE;
    02217         }
    02218
    02219         if( mode == FOG_NONE)
    02220         {
    02221             // just disable
    02222             hr = __SetRenderState(fogType, D3DFOG_NONE );
    02223             hr = __SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE);
    02224         }
    02225         else
    02226         {
    02227             // Allow fog
    02228             hr = __SetRenderState( D3DRENDERSTATE_FOGENABLE, TRUE );
    02229             hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
    02230             switch(mode)
    02231             {
    02232             case FOG_EXP:
    02233                 hr = __SetRenderState( fogType, D3DFOG_EXP);
    02234                 break;
    02235             case FOG_EXP2:
    02236                 hr = __SetRenderState( fogType, D3DFOG_EXP2);
    02237                 break;
    02238             case FOG_LINEAR:
    02239                 hr = __SetRenderState( fogType, D3DFOG_LINEAR);
    02240                 break;
    02241
    02242             }
    02243
    02244             hr = __SetRenderState( D3DRENDERSTATE_FOGCOLOR, colour.getAsLongARGB() );
    02245             hr = __SetRenderState( D3DRENDERSTATE_FOGSTART, *((LPDWORD)(&start)) );
    02246             hr = __SetRenderState( D3DRENDERSTATE_FOGEND, *((LPDWORD)(&end)) );
    02247             hr = __SetRenderState( D3DRENDERSTATE_FOGDENSITY, *((LPDWORD)(&density)) );
    02248         }
    02249
    02250
    02251     }
    02252
    02253     //---------------------------------------------------------------------
    02254     void D3DRenderSystem::convertColourValue(const ColourValue& colour, unsigned long* pDest)
    02255     {
    02256         *pDest = colour.getAsLongARGB();
    02257     }
    02258     //---------------------------------------------------------------------
    02259     void D3DRenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect,
    02260         Real nearPlane, Real farPlane, Matrix4& dest, bool forGpuProgram)
    02261     {
    02262         Radian theta(fovy * 0.5);
    02263         Real h = 1 / Math::Tan(theta);
    02264         Real w = h / aspect;
    02265         Real q, qn;
    02266         if (farPlane == 0)
    02267         {
    02268             q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
    02269             qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
    02270         }
    02271         else
    02272         {
    02273             q = farPlane / ( farPlane - nearPlane );
    02274             qn = -q * nearPlane;
    02275         }
    02276
    02277         dest = Matrix4::ZERO;
    02278         dest[0][0] = w;
    02279         dest[1][1] = h;
    02280
    02281         if (forGpuProgram)
    02282         {
    02283             dest[2][2] = -q;
    02284             dest[3][2] = -1.0f;
    02285         }
    02286         else
    02287         {
    02288             dest[2][2] = q;
    02289             dest[3][2] = 1.0f;
    02290         }
    02291
    02292         dest[2][3] = qn;
    02293
    02294     }
    02295     //---------------------------------------------------------------------
    02296     void D3DRenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, Real farPlane,
    02297         Matrix4& dest, bool forGpuProgram )
    02298     {
    02299         Radian thetaY (fovy / 2.0f);
    02300         Real tanThetaY = Math::Tan(thetaY);
    02301
    02302         //Real thetaX = thetaY * aspect;
    02303         Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
    02304         Real half_w = tanThetaX * nearPlane;
    02305         Real half_h = tanThetaY * nearPlane;
    02306         Real iw = 1.0 / half_w;
    02307         Real ih = 1.0 / half_h;
    02308         Real q;
    02309         if (farPlane == 0)
    02310         {
    02311             q = 0;
    02312         }
    02313         else
    02314         {
    02315             q = 1.0 / (farPlane - nearPlane);
    02316         }
    02317
    02318         dest = Matrix4::ZERO;
    02319         dest[0][0] = iw;
    02320         dest[1][1] = ih;
    02321         dest[2][2] = q;
    02322         dest[2][3] = -nearPlane / (farPlane - nearPlane);
    02323         dest[3][3] = 1;
    02324
    02325         if (forGpuProgram)
    02326         {
    02327             dest[2][2] = -dest[2][2];
    02328         }
    02329     }
    02330     //---------------------------------------------------------------------
    02331     void D3DRenderSystem::_setRasterisationMode(SceneDetailLevel level)
    02332     {
    02333         D3DFILLMODE d3dmode;
    02334
    02335         switch(level)
    02336         {
    02337         case SDL_POINTS:
    02338             d3dmode = D3DFILL_POINT;
    02339             break;
    02340         case SDL_WIREFRAME:
    02341             d3dmode = D3DFILL_WIREFRAME;
    02342             break;
    02343         case SDL_SOLID:
    02344             d3dmode = D3DFILL_SOLID;
    02345             break;
    02346
    02347         }
    02348
    02349         HRESULT hr = __SetRenderState(D3DRENDERSTATE_FILLMODE, d3dmode);
    02350         if (FAILED(hr))
    02351         {
    02352             Except(hr, "Error setting rasterisation mode.",
    02353                 "D3DRenderSystem::setRasterisationMode");
    02354         }
    02355
    02356
    02357     }
    02358     //---------------------------------------------------------------------
    02359     void D3DRenderSystem::setStencilCheckEnabled(bool enabled)
    02360     {
    02361         // Allow stencilling
    02362         HRESULT hr = __SetRenderState(D3DRENDERSTATE_STENCILENABLE, enabled);
    02363         if (FAILED(hr))
    02364             Except(hr, "Error enabling / disabling stencilling.",
    02365             "D3DRenderSystem::setStencilCheckEnabled");
    02366
    02367     }
    02368     //---------------------------------------------------------------------
    02369     void D3DRenderSystem::setStencilBufferParams(CompareFunction func, ulong refValue,
    02370         ulong mask, StencilOperation stencilFailOp,
    02371         StencilOperation depthFailOp, StencilOperation passOp,
    02372         bool twoSidedOperation)
    02373     {
    02374         HRESULT hr;
    02375
    02376         // D3D7 does not support 2-sided stencil operations
    02377         if (twoSidedOperation)
    02378             Except(Exception::ERR_INVALIDPARAMS, "Direct3D7 does not support 2-sided stencil ops",
    02379                "D3DRenderSystem::setStencilBufferParams");
    02380
    02381         // Function
    02382         hr = __SetRenderState(D3DRENDERSTATE_STENCILFUNC,
    02383             convertCompareFunction(func));
    02384
    02385         if (FAILED(hr))
    02386             Except(hr, "Error setting stencil buffer test function.",
    02387             "D3DRenderSystem::setStencilBufferParams");
    02388
    02389         // reference value
    02390         hr = __SetRenderState(D3DRENDERSTATE_STENCILREF, refValue);
    02391         if (FAILED(hr))
    02392             Except(hr, "Error setting stencil buffer reference value.",
    02393             "D3DRenderSystem::setStencilBufferParams");
    02394
    02395         // mask
    02396         hr = __SetRenderState(D3DRENDERSTATE_STENCILMASK, mask);
    02397         if (FAILED(hr))
    02398             Except(hr, "Error setting stencil buffer mask.",
    02399             "D3DRenderSystem::setStencilBufferParams");
    02400
    02401         // fail op
    02402         hr = __SetRenderState(D3DRENDERSTATE_STENCILFAIL,
    02403             convertStencilOp(stencilFailOp));
    02404         if (FAILED(hr))
    02405             Except(hr, "Error setting stencil fail operation.",
    02406             "D3DRenderSystem::setStencilBufferParams");
    02407
    02408         // depth fail op
    02409         hr = __SetRenderState(D3DRENDERSTATE_STENCILZFAIL,
    02410             convertStencilOp(depthFailOp));
    02411         if (FAILED(hr))
    02412             Except(hr, "Error setting stencil depth fail operation.",
    02413             "D3DRenderSystem::setStencilBufferParams");
    02414
    02415         // pass op
    02416         hr = __SetRenderState(D3DRENDERSTATE_STENCILPASS,
    02417             convertStencilOp(passOp));
    02418         if (FAILED(hr))
    02419             Except(hr, "Error setting stencil pass operation.",
    02420             "D3DRenderSystem::setStencilBufferParams");
    02421     }
    02422     //---------------------------------------------------------------------
    02423     D3DCMPFUNC D3DRenderSystem::convertCompareFunction(CompareFunction func)
    02424     {
    02425         switch(func)
    02426         {
    02427         case CMPF_ALWAYS_FAIL:
    02428             return D3DCMP_NEVER;
    02429         case CMPF_ALWAYS_PASS:
    02430             return D3DCMP_ALWAYS;
    02431         case CMPF_LESS:
    02432             return D3DCMP_LESS;
    02433         case CMPF_LESS_EQUAL:
    02434             return D3DCMP_LESSEQUAL;
    02435         case CMPF_EQUAL:
    02436             return D3DCMP_EQUAL;
    02437         case CMPF_NOT_EQUAL:
    02438             return D3DCMP_NOTEQUAL;
    02439         case CMPF_GREATER_EQUAL:
    02440             return D3DCMP_GREATEREQUAL;
    02441         case CMPF_GREATER:
    02442             return D3DCMP_GREATER;
    02443         };
    02444         // to shut the compiler up
    02445         return D3DCMP_ALWAYS;
    02446     }
    02447     //---------------------------------------------------------------------
    02448     D3DSTENCILOP D3DRenderSystem::convertStencilOp(StencilOperation op)
    02449     {
    02450         switch(op)
    02451         {
    02452         case SOP_KEEP:
    02453             return D3DSTENCILOP_KEEP;
    02454         case SOP_ZERO:
    02455             return D3DSTENCILOP_ZERO;
    02456         case SOP_REPLACE:
    02457             return D3DSTENCILOP_REPLACE;
    02458         case SOP_INCREMENT:
    02459             return D3DSTENCILOP_INCRSAT;
    02460         case SOP_DECREMENT:
    02461             return D3DSTENCILOP_DECRSAT;
    02462         case SOP_INCREMENT_WRAP:
    02463             return D3DSTENCILOP_INCR;
    02464         case SOP_DECREMENT_WRAP:
    02465             return D3DSTENCILOP_DECR;
    02466         case SOP_INVERT:
    02467             return D3DSTENCILOP_INVERT;
    02468         };
    02469         // To shut the compiler up
    02470         return D3DSTENCILOP_KEEP;
    02471     }
    02472
    02473     DWORD D3DRenderSystem::_getCurrentAnisotropy(size_t unit)
    02474     {
    02475         DWORD oldVal;
    02476         mlpD3DDevice->GetTextureStageState(unit, D3DTSS_MAXANISOTROPY, &oldVal);
    02477         return oldVal;
    02478     }
    02479
    02480
    02481     void D3DRenderSystem::_setTextureUnitFiltering(size_t unit,
    02482         FilterType ftype, FilterOptions filter)
    02483     {
    02484         __SetTextureStageState(unit, _getFilterCode(ftype), _getFilter(ftype, filter));
    02485     }
    02486
    02487     void D3DRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
    02488     {
    02489         if ((DWORD)maxAnisotropy > mD3DDeviceDesc.dwMaxAnisotropy)
    02490             maxAnisotropy = mD3DDeviceDesc.dwMaxAnisotropy;
    02491
    02492         if (_getCurrentAnisotropy(unit) != maxAnisotropy)
    02493             __SetTextureStageState( unit, D3DTSS_MAXANISOTROPY, maxAnisotropy );
    02494     }
    02495
    02496     void D3DRenderSystem::setVertexDeclaration(VertexDeclaration* decl)
    02497     {
    02498         // TODO
    02499     }
    02500
    02501     void D3DRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
    02502     {
    02503         // TODO
    02504     }
    02505     //-----------------------------------------------------------------------
    02506     D3DTEXTURESTAGESTATETYPE D3DRenderSystem::_getFilterCode(FilterType ft) const
    02507     {
    02508         switch (ft)
    02509         {
    02510         case FT_MIN:
    02511             return D3DTSS_MINFILTER;
    02512             break;
    02513         case FT_MAG:
    02514             return D3DTSS_MAGFILTER;
    02515             break;
    02516         case FT_MIP:
    02517             return D3DTSS_MIPFILTER;
    02518             break;
    02519         }
    02520
    02521         // to keep compiler happy
    02522         return D3DTSS_MINFILTER;
    02523     }
    02524     //-----------------------------------------------------------------------
    02525     DWORD D3DRenderSystem::_getFilter(FilterType ft, FilterOptions fo) const
    02526     {
    02527         switch (ft)
    02528         {
    02529         case FT_MIN:
    02530             switch( fo )
    02531             {
    02532                 // NOTE: Fall through if device doesn't support requested type
    02533             case FO_ANISOTROPIC:
    02534                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC )
    02535                 {
    02536                     return D3DTFN_ANISOTROPIC;
    02537                     break;
    02538                 }
    02539             case FO_LINEAR:
    02540                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR )
    02541                 {
    02542                     return D3DTFN_LINEAR;
    02543                     break;
    02544                 }
    02545             case FO_POINT:
    02546             case TFO_NONE:
    02547                 return D3DTFN_POINT;
    02548                 break;
    02549             }
    02550             break;
    02551         case FT_MAG:
    02552             switch( fo )
    02553             {
    02554             // NOTE: Fall through if device doesn't support requested type
    02555             case FO_ANISOTROPIC:
    02556                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC )
    02557                 {
    02558                     return D3DTFG_ANISOTROPIC;
    02559                     break;
    02560                 }
    02561             case FO_LINEAR:
    02562                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR )
    02563                 {
    02564                     return D3DTFG_LINEAR;
    02565                     break;
    02566                 }
    02567             case FO_POINT:
    02568             case FO_NONE:
    02569                 return D3DTFG_POINT;
    02570                 break;
    02571             }
    02572             break;
    02573         case FT_MIP:
    02574             switch( fo )
    02575             {
    02576             case FO_ANISOTROPIC:
    02577             case FO_LINEAR:
    02578                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR )
    02579                 {
    02580                     return D3DTFP_LINEAR;
    02581                     break;
    02582                 }
    02583             case FO_POINT:
    02584                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR )
    02585                 {
    02586                     return D3DTFP_POINT;
    02587                     break;
    02588                 }
    02589             case TFO_NONE:
    02590                 return D3DTFP_NONE;
    02591                 break;
    02592             }
    02593             break;
    02594         }
    02595
    02596         // should never get here
    02597         return 0;
    02598     }
    02599     //---------------------------------------------------------------------
    02600     void D3DRenderSystem::setNormaliseNormals(bool normalise)
    02601     {
    02602         __SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS,
    02603             normalise ? TRUE : FALSE);
    02604     }
    02605     //---------------------------------------------------------------------
    02606     HRESULT D3DRenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
    02607     {
    02608         HRESULT hr;
    02609         DWORD oldVal;
    02610
    02611         if ( FAILED( hr = mlpD3DDevice->GetRenderState(state, &oldVal) ) )
    02612             return hr;
    02613         if ( oldVal == value )
    02614             return D3D_OK;
    02615         else
    02616             return mlpD3DDevice->SetRenderState(state, value);
    02617     }
    02618     //---------------------------------------------------------------------
    02619     HRESULT D3DRenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
    02620     {
    02621         HRESULT hr;
    02622         DWORD oldVal;
    02623
    02624         if ( FAILED( hr = mlpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) )
    02625             return hr;
    02626         if ( oldVal == value )
    02627             return D3D_OK;
    02628         else
    02629             return mlpD3DDevice->SetTextureStageState(stage, type, value);
    02630     }
    02631
    02632     //---------------------------------------------------------------------
    02633     void D3DRenderSystem::clearFrameBuffer(unsigned int buffers,
    02634         const ColourValue& colour, Real depth, unsigned short stencil)
    02635     {
    02636         DWORD flags = 0;
    02637         if (buffers & FBT_COLOUR)
    02638         {
    02639             flags |= D3DCLEAR_TARGET;
    02640         }
    02641         if (buffers & FBT_DEPTH)
    02642         {
    02643             flags |= D3DCLEAR_ZBUFFER;
    02644         }
    02645         // Only try to clear the stencil if supported, otherwise it will fail
    02646         if (buffers & FBT_STENCIL && mCapabilities->hasCapability(RSC_HWSTENCIL))
    02647         {
    02648             flags |= D3DCLEAR_STENCIL;
    02649         }
    02650         HRESULT hr;
    02651         if( FAILED( hr = mlpD3DDevice->Clear(
    02652             0,
    02653             NULL,
    02654             flags,
    02655             colour.getAsLongARGB(),
    02656             depth,
    02657             stencil ) ) )
    02658         {
    02659             String msg = getErrorDescription(hr);
    02660             Except( hr, "Error clearing frame buffer : "
    02661                 + msg, "D3DRenderSystem::clearFrameBuffer" );
    02662         }
    02663     }
    02664     //---------------------------------------------------------------------
    02665     void D3DRenderSystem::_makeProjectionMatrix(Real left, Real right,
    02666         Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
    02667         bool forGpuProgram)
    02668     {
    02669         Real width = right - left;
    02670         Real height = top - bottom;
    02671         Real q, qn;
    02672         if (farPlane == 0)
    02673         {
    02674             q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
    02675             qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
    02676         }
    02677         else
    02678         {
    02679             q = farPlane / ( farPlane - nearPlane );
    02680             qn = -q * nearPlane;
    02681         }
    02682         dest = Matrix4::ZERO;
    02683         dest[0][0] = 2 * nearPlane / width;
    02684         dest[0][2] = (right+left) / width;
    02685         dest[1][1] = 2 * nearPlane / height;
    02686         dest[1][2] = (top+bottom) / height;
    02687         if (forGpuProgram)
    02688         {
    02689             dest[2][2] = -q;
    02690             dest[3][2] = -1.0f;
    02691         }
    02692         else
    02693         {
    02694             dest[2][2] = q;
    02695             dest[3][2] = 1.0f;
    02696         }
    02697         dest[2][3] = qn;
    02698     }
    02699
    02700     //---------------------------------------------------------------------
    02701     void D3DRenderSystem::setClipPlanes(const PlaneList& clipPlanes)
    02702     {
    02703         size_t i;
    02704         size_t numClipPlanes;
    02705         D3DVALUE dx7ClipPlane[4];
    02706         DWORD mask = 0;
    02707         HRESULT hr;
    02708         numClipPlanes = clipPlanes.size();
    02709
    02710         for (i = 0; i < numClipPlanes; ++i)
    02711         {
    02712             const Plane& plane = clipPlanes[i];
    02713
    02714             dx7ClipPlane[0] = plane.normal.x;
    02715             dx7ClipPlane[1] = plane.normal.y;
    02716             dx7ClipPlane[2] = plane.normal.z;
    02717             dx7ClipPlane[3] = -plane.d;
    02718
    02719             hr = mlpD3DDevice->SetClipPlane(i, dx7ClipPlane);
    02720             if (FAILED(hr))
    02721             {
    02722                 Except(hr, "Unable to set clip plane",
    02723                     "D3D7RenderSystem::setClipPlanes");
    02724             }
    02725
    02726             mask |= (1 << i);
    02727         }
    02728
    02729         hr = mlpD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, mask);
    02730         if (FAILED(hr))
    02731         {
    02732             Except(hr, "Unable to set render state for clip planes",
    02733                 "D3D7RenderSystem::setClipPlanes");
    02734         }
    02735     }
    02736
    02737     // ------------------------------------------------------------------
    02738     void D3DRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
    02739     {
    02740         float plane[4] = { A, B, C, D };
    02741         mlpD3DDevice->SetClipPlane (index, plane);
    02742     }
    02743
    02744     // ------------------------------------------------------------------
    02745     void D3DRenderSystem::enableClipPlane (ushort index, bool enable)
    02746     {
    02747         DWORD prev;
    02748         mlpD3DDevice->GetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, &prev);
    02749         __SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, prev | (1 << index));
    02750     }
    02751     //---------------------------------------------------------------------
    02752     HardwareOcclusionQuery* D3DRenderSystem::createHardwareOcclusionQuery(void)
    02753     {
    02754         return (HardwareOcclusionQuery*) 0; // Hardware occlusion is not supported when DirectX7 is used
    02755     }
    02756     //-----------------------------------------------------------------------
    02757     void D3DRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
    02758     {
    02759         // D3D7 does not have a colour write mask setting, so emulate it using
    02760         // scene blending, on the assumption that setSceneBlend will be called
    02761         // before this
    02762         if (red || green || blue || alpha)
    02763         {
    02764             // restore saved scene blend
    02765             _setSceneBlending(mSavedSrcFactor, mSavedDestFactor);
    02766         }
    02767         else
    02768         {
    02769             _setSceneBlending(SBF_ZERO, SBF_ONE);
    02770         }
    02771     }
    02772     //---------------------------------------------------------------------
    02773     Real D3DRenderSystem::getHorizontalTexelOffset(void)
    02774     {
    02775         // D3D considers the origin to be in the center of a pixel
    02776         return -0.5f;
    02777     }
    02778     //---------------------------------------------------------------------
    02779     Real D3DRenderSystem::getVerticalTexelOffset(void)
    02780     {
    02781         // D3D considers the origin to be in the center of a pixel
    02782         return -0.5f;
    02783     }
    02784     //---------------------------------------------------------------------
    02785     void D3DRenderSystem::_applyObliqueDepthProjection(Matrix4& matrix,
    02786         const Plane& plane, bool forGpuProgram)
    02787     {
    02788         // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
    02789
    02790         // Calculate the clip-space corner point opposite the clipping plane
    02791         // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
    02792         // transform it into camera space by multiplying it
    02793         // by the inverse of the projection matrix
    02794
    02795         /* generalised version
    02796         Vector4 q = matrix.inverse() *
    02797         Vector4(Math::Sign(plane.normal.x), Math::Sign(plane.normal.y), 1.0f, 1.0f);
    02798         */
    02799         Vector4 q;
    02800         q.x = Math::Sign(plane.normal.x) / matrix[0][0];
    02801         q.y = Math::Sign(plane.normal.y) / matrix[1][1];
    02802         q.z = 1.0F;
    02803         // flip the next bit from Lengyel since we're right-handed
    02804         //q.w = (1.0F - matrix[2][2]) / matrix[2][3];
    02805         q.w = (1.0F + matrix[2][2]) / matrix[2][3];
    02806
    02807         // Calculate the scaled plane vector
    02808         Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
    02809         Vector4 c = clipPlane4d * (1.0F / (clipPlane4d.dotProduct(q)));
    02810
    02811         // Replace the third row of the projection matrix
    02812         matrix[2][0] = c.x;
    02813         matrix[2][1] = c.y;
    02814         // flip the next bit from Lengyel since we're right-handed
    02815         //matrix[2][2] = c.z;
    02816         matrix[2][2] = -c.z;
    02817         matrix[2][3] = c.w;
    02818
    02819     }
    02820     //---------------------------------------------------------------------
    02821     Real D3DRenderSystem::getMinimumDepthInputValue(void)
    02822     {
    02823         // Range [0.0f, 1.0f]
    02824         return 0.0f;
    02825     }
    02826     //---------------------------------------------------------------------
    02827     Real D3DRenderSystem::getMaximumDepthInputValue(void)
    02828     {
    02829         // Range [0.0f, 1.0f]
    02830         // D3D inverts even identity view matrices, so maximum INPUT is -1.0
    02831         return -1.0f;
    02832     }
    02833
    02834
    02835 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:19 2004