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