📄 directx8visualsystem.cpp
字号:
// QGEngine
#include "DirectX8VisualSystem.h"
#include "../../Main/QLogManager.h"
#include "../../Main/QResourceManager.h"
#include "../../Main/QString.h"
#include "../../Main/Exception.h"
#include "../../XMLParse/XMLDocument.h"
#include "../../Main/QMath.h"
#include "D3DSettings.h"
#include "Win32Window.h"
#include "Dx8Enumeration.h"
#include "../../Main/QLight.h"
#include "../../Main/QViewPort.h"
#include "../../Main/QTextureManager.h"
#include "../../Main/QMaterialManager.h"
#include "../../Main/QHardwareBufferManager.h"
#include "D3D8BufferFactory.h"
#include "D3D8TextureFactory.h"
#include "D3D8Texture.h"
#include "D3D8VertexBuffer.h"
#include "D3D8IndexBuffer.h"
#include "D3DMapping.h"
#include "DxUtil.h"
D3DXCOLOR ColorToD3DXCOLOR(const Color& color)
{
// return D3DXCOLOR((Real32)color.red/255,(Real32)color.green/255,(Real32)color.blue/255,(Real32)color.alpha/255);
return D3DXCOLOR( Int32(color) );
}
D3DRECT RectToD3DRECT(const Rect& rect)
{
D3DRECT r;
r.x1 = rect.x;
r.y1 = rect.y;
r.x2 = rect.x+rect.width;
r.y2 = rect.y+rect.height;
return r;
}
void Matrix4ToD3DXMATRIX(const Matrix4& mat,D3DXMATRIX& dmat)
{
for(Int32 i=0;i<4;++i)
for( Int32 j=0;j<4;++j )
dmat.m[i][j] = mat.m[i][j];
}
DirectX8VisualSystem::DirectX8VisualSystem(HINSTANCE hInst):
m_pd3d(NULL),m_pd3dDevice(NULL),m_HInst(hInst)
{
}
DirectX8VisualSystem::~DirectX8VisualSystem()
{
Destroy();
}
Bool DirectX8VisualSystem::Initialize()
{
if( m_HInst == 0 )
{
LOGLOW("DirectX8VisualSystem::Initialize : HINSTANCE Required");
return false;
}
m_pd3d = Direct3DCreate8(D3D_SDK_VERSION);
if( m_pd3d == NULL )
{
LOGLOW("DirectX8VisualSystem::Initialize : Fail to Create Direct3D");
return false;
}
// 创建窗口
Win32Window* pWin = (Win32Window*)m_WindowDevice;
if( !pWin )
{
//在此之前没有创建窗口,则根据Settings创建窗口
pWin = new Win32Window;
pWin->Create("QGEnginWindow", true ,640,480,0,0,m_HInst);
AddWindowDevice(pWin);
}
HWND hWnd = pWin->getWindowHandle();
if( hWnd == 0 )
{
LOGLOW("DirectX8VisualSystem::Initialize : HWND Required");
return false;
}
DX8Enumeration d3dEnum(m_pd3d);
d3dEnum.BuildDeviceList();
LoadSettings(&d3dEnum);
D3DAdapterInfo adapter = d3dEnum.GetCurrentAdapter();
D3DDeviceInfo device = adapter.devices[adapter.dwCurrentDevice];
D3DModeInfo mode = device.modes[device.dwCurrentMode];
if( !device.bWindowed )
{
if( !pWin->TurnToFullScreen() ) // force to windowed mode
{
if( device.bCanDoWindowed )
device.bWindowed =true;
else
{
LOGBOREME("Fail to Toggle to Fullscreen Mode");
return false;
}
}
}
else
{
Int32 w,h,l,t;
m_WindowDevice->getMetrics(w,h,l,t);
if( mode.Width!= w || mode.Height!= h )
m_WindowDevice->Resize(mode.Width,mode.Height);
}
//创建D3D设备
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = !pWin->isFullScreen();
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = d3dpp.Windowed ? device.MultiSampleTypeWindowed : device.MultiSampleTypeFullscreen;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil = d3dEnum.IsUseDepthStencilBuffer();
d3dpp.AutoDepthStencilFormat = mode.DepthStencilFormat;
d3dpp.hDeviceWindow = hWnd;
if( d3dpp.Windowed )
{
Int32 width,height,left,top;
pWin->getMetrics(width,height,left,top);
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight= height;
d3dpp.BackBufferFormat= adapter.d3ddmDesktop.Format;
}
else
{
d3dpp.BackBufferWidth = mode.Width;
d3dpp.BackBufferHeight= mode.Height;
d3dpp.BackBufferFormat= mode.Format;
}
if( device.d3dCaps.PrimitiveMiscCaps & D3DPMISCCAPS_NULLREFERENCE )
{
LOGBOREME("DirectX8VisualSystem::Initialize : Null ref device that can't render anything");
}
if( FAILED( m_pd3d->CreateDevice( d3dEnum.GetCurrentAdapterIdx(), device.DeviceType, hWnd,
mode.dwBehavior,&d3dpp, &m_pd3dDevice ) ) )
{
LOGBOREME("DirectX8VisualSystem::Initialize : Fail to Create Direct3DDevice");
return false;
}
m_pd3dDevice->GetDeviceCaps(&m_Caps);
//注册BufferFactory
HardwareBufferManager::Instance().SetBufferFactory(new D3D8BufferFactory(m_pd3dDevice));
//注册TextureFactory
TextureManager::Instance().SetTextureFactory(new D3D8TextureFactory(m_pd3dDevice));
MaterialManager::Instance();
//也许 我们还需要对鼠标进行剪切
//...
return true;
}
void DirectX8VisualSystem::Destroy()
{
IVisualSys::Destroy();
HardwareBufferManager::Destroy();
TextureManager::Destroy();
MaterialManager::Destroy();
SAFE_RELEASE(m_pd3dDevice);
SAFE_RELEASE(m_pd3d);
}
void DirectX8VisualSystem::LoadSettings(DX8Enumeration* d3dEnum)
{
XML::XMLDocument* configFile = (XML::XMLDocument*) ResourceManager::Instance().GetResource("QConfig.xml");
XML::XMLTag &settingTag = configFile->getXMLRootNode().getChild("Settings").getTag();
XML::XMLAttribute* tmp;
tmp = settingTag.getAttribute("showConfigDlg");
if( tmp && tmp->Value().toBool() )
{
//在对话框中配置
CD3DSettingsDialog* dlg = new CD3DSettingsDialog(d3dEnum);
dlg->ShowDialog( m_HInst,((Win32Window*)m_WindowDevice)->getWindowHandle() );
settingTag.setAttribute("adapterIndex",
String::IntToString(d3dEnum->GetCurrentAdapterIdx()));
settingTag.setAttribute("deviceIndex",
String::IntToString(d3dEnum->GetCurrentAdapter().dwCurrentDevice));
settingTag.setAttribute("modeIndex",
String::IntToString(d3dEnum->GetCurrentAdapter().devices[d3dEnum->GetCurrentAdapter().dwCurrentDevice].dwCurrentMode));
settingTag.setAttribute("windowed",
String::BoolToString(d3dEnum->GetCurrentAdapter().devices[d3dEnum->GetCurrentAdapter().dwCurrentDevice].bWindowed));
settingTag.setAttribute("enableBuffer",
String::BoolToString(d3dEnum->IsUseDepthStencilBuffer()));
settingTag.setAttribute("useMixedVertexProcessing",
String::BoolToString(d3dEnum->IsMixedVertexProcessing()));
delete dlg;
}
else
{
tmp = settingTag.getAttribute(String("useDefault"));
if( !tmp || !tmp->Value().toBool() )
{
try
{
d3dEnum->SetCurrentAdapterIdx(settingTag.getAttribute("adapterIndex")->Value().toInt());
d3dEnum->GetCurrentAdapter().dwCurrentDevice = settingTag.getAttribute("deviceIndex")->Value().toInt();
d3dEnum->GetCurrentAdapter().devices[d3dEnum->GetCurrentAdapter().dwCurrentDevice].dwCurrentMode =
settingTag.getAttribute("modeIndex")->Value().toInt();
d3dEnum->GetCurrentAdapter().devices[d3dEnum->GetCurrentAdapter().dwCurrentDevice].bWindowed =
settingTag.getAttribute("windowed")->Value().toBool();
d3dEnum->UseDepthStencilBuffer( settingTag.getAttribute("enableBuffer")->Value().toBool() );
d3dEnum->UseMixedVertexProcessing(settingTag.getAttribute("useMixedVertexProcessing")->Value().toBool());
}
catch (...)
{
LOGLOW("FAIL to Load VisualSystem Settings");
}
}
}
}
/************************************************************************/
/* 灯光 */
/************************************************************************/
void DirectX8VisualSystem::EnableLighting(Bool able)
{
if( FAILED(m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,able) ))
{
LOGLOW("DirectX8VisualSystem::EnableLighting : Cannot enable/disable the lighting");
}
}
void DirectX8VisualSystem::SetAmbientLight(Color color)
{
HRESULT hr = m_pd3dDevice->SetRenderState(D3DRS_AMBIENT,color);
if( FAILED(hr))
LOGLOW("DirectX8VisualSystem::SetAmbientLight : Cannot set the AmbientLight");
}
void DirectX8VisualSystem::_addLight(Light* light)
{
for( Int32 i=0;i<MAX_LIGHTS;++i)
{
if( m_Lights[i]==NULL )
{
m_Lights[i] = light;
++m_LightsNum;
_setD3D8Light(i,light);
break;
}
}
if( i==MAX_LIGHTS )
LOGLOW("DirectX8VisualSystem::_addLight : Too Many Lights");
}
void DirectX8VisualSystem::RemoveLight(String& name,Light** pLightOut)
{
for( Int32 i=0;i<MAX_LIGHTS;++i)
{
if( m_Lights[i] && m_Lights[i]->getName()==name )
{
m_pd3dDevice->LightEnable(i,FALSE);
*pLightOut = m_Lights[i];
m_Lights[i] = NULL;
--m_LightsNum;
break;
}
}
if( i==MAX_LIGHTS)
LOGLOW("DirectX8VisualSystem::_removeLight : Cannot locate the light to remove");
}
void DirectX8VisualSystem::RemoveAllLights()
{
for( Int32 i=0;i<MAX_LIGHTS;++i )
{
if( m_Lights[i] )
{
m_pd3dDevice->LightEnable(i,FALSE);
--m_LightsNum;
}
}
}
void DirectX8VisualSystem::_modifyLight(Light* lt)
{
for( Int32 i=0;i<MAX_LIGHTS;++i)
{
if( m_Lights[i] == lt )
{
_setD3D8Light(i,lt);
break;
}
}
if( i == MAX_LIGHTS )
LOGLOW("DirectX8VisualSystem::_modifyLight : Cannot locate the light to modify");
}
void DirectX8VisualSystem::_setD3D8Light(Int32 index,Light* lt)
{
if( lt->isStateON() )
{
//创建D3D8灯光
D3DLIGHT8 d3dLight;
ZeroMemory(&d3dLight,sizeof(d3dLight));
d3dLight.Type = D3DMapping::Get(lt->getLightType());
if( d3dLight.Type == D3DLIGHT_SPOT )
{
d3dLight.Falloff = lt->getSpotlightFalloff();
d3dLight.Theta = Math::AngleUnitsToRadians( lt->getSpotlightInnerAngle() );
d3dLight.Phi = Math::AngleUnitsToRadians( lt->getSpotlightOuterAngle() );
}
Color color = lt->getDiffuseColor();
d3dLight.Diffuse = ColorToD3DXCOLOR(color);
color = lt->getSpecularColor();
d3dLight.Specular= ColorToD3DXCOLOR(color);
Vector3 vec;
if( lt->getLightType() != LT_DIRECTIONAL )
{
vec = lt->getPosition();
d3dLight.Position = D3DXVECTOR3(vec.x,vec.y,vec.z);
}
if( lt->getLightType() != LT_POINT )
{
vec = lt->getDirection();
d3dLight.Direction = D3DXVECTOR3(vec.x,vec.y,vec.z);
}
d3dLight.Range = lt->getAttenuationRange();
d3dLight.Attenuation0 = lt->getAttenuationConstant();
d3dLight.Attenuation1 = lt->getAttenuationLinear();
d3dLight.Attenuation2 = lt->getAttenuationQuadric();
if( FAILED( m_pd3dDevice->SetLight(index,&d3dLight) ))
{
LOGLOW("DirectX8VisualSystem::_setD3D8Light : Cannot Set the Light");
return;
}
}
if( FAILED( m_pd3dDevice->LightEnable(index,lt->isStateON() ) ) )
{
LOGLOW("DirectX8VisualSystem::_setD3D8Light : Cannot Enable the Light");
return;
}
lt->clearModifiedFlag();
}
/************************************************************************/
/* 贴图设置 */
/************************************************************************/
void DirectX8VisualSystem::_setTexture(Int32 stage,const String& texName,Bool enable )
{
D3D8Texture* dt = (D3D8Texture*)TextureManager::Instance().GetTexture(texName);
if( dt && enable )
{
LPDIRECT3DTEXTURE8 ptex = dt->GetTexture();
if( m_TexStageDesc[stage].pTex!=dt )
{
if( FAILED(m_pd3dDevice->SetTexture(stage,ptex)) )
{
LOGLOW( String("DirectX8VisualSystem::_setTexture : Cannot SetTexture :"+texName));
return;
}
m_TexStageDesc[stage].pTex = dt;
}
}
else
{
//如果原本在state层使用了texture,则禁用它
if( m_TexStageDesc[stage].pTex != 0 )
{
if( FAILED(m_pd3dDevice->SetTexture(stage,0)) )
{
LOGLOW( String("DirectX8VisualSystem::_setTexture : Cannot Disable the Texture : "+texName) );
return;
}
m_TexStageDesc[stage].pTex = 0;
}
if( FAILED( m_pd3dDevice->SetTextureStageState(stage,D3DTSS_COLOROP,D3DTOP_DISABLE )) )
{
LOGLOW("DirectX8VisualSystem::_setTexture : Cannot set ColorOperation disabled");
return;
}
}
}
void DirectX8VisualSystem::_setTextureBlendMode(Int32 stage,LayerBlendModeEx mode)
{
D3DTEXTURESTAGESTATETYPE tss;
if( mode.blendType = LBT_COLOUR )
tss = D3DTSS_COLOROP;
else
tss = D3DTSS_ALPHAOP;
//要求使用 手动因子 (manual factor)
if( mode.operation == LBX_BLEND_MANUAL )
{
if( FAILED(m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,D3DXCOLOR(0.0, 0.0, 0.0, mode.factor))) )
{
LOGLOW("DirectX8VisualSystem::_setTextureBlendMode : Cannot set Texture manual factor");
return;
}
}
if( FAILED( m_pd3dDevice->SetTextureStageState(stage,tss,D3DMapping::Get(mode.operation,&m_Caps) ) ) )
{
LOGLOW("DirectX8VisualSystem::_setTextureBlendMode : Cannot set Texture Render Operation");
}
//设置Arg1
D3DXCOLOR color;
if(mode.blendType == LBT_COLOUR )
{
tss = D3DTSS_COLORARG1;
color = D3DXCOLOR(mode.colourArg1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -