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