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

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:06 2004