dxut.h:DXUT进阶(翻译)



DXUT进阶

概要
这个指南涵盖了更多DXUT高级应用.这个指南里大部分功能是可选,为了以最小代价来增强你应用.DXUT提供了个简单基于GUI系统精灵和个设备设置对话框.另外,它还提供了些摄像机类.
这个指南结果是个具有完善功能GUI用于更改设备和场景设置.它将有按钮,滑块,和文本来示范这些功能.
导航
• DXUT摄像机
• DXUT对话框
• 资源管理
• 3D设置对话框
• 文本渲染
DXUT摄像机
DXUT中CModelViewerCamera类可以简单管理视图变换和透视变换,就像GUI功能样.
CModelViewerCamerag_Camera;//Amodelviewingcamera
摄像机类提供个功能是创建视图和透视矩阵.有了这个摄像机,没有必要担心这些矩阵.反而,你可以指定你在哪,你看着什么,还有窗口大小.然后,把这些参数传递给摄像机对象,它会在后台创建这些矩阵.
这里我们设置摄像机部分视图参数.我们指定我们在哪,和我们看着什么.
//Initializethecamera
D3DXVECTOR3Eye(0.0f,0.0f,-800.0f);
D3DXVECTOR3At(0.0f,0.0f,0.0f);
g_Camera.SetViewParams(&Eye,&At);
接下来,我们指定摄像机投影参数.也就是说,我们需要提供观察角度,纵横比,和视图截锥近、远裁剪面.这些信息跟的前指南提供样,区别是,你不必担心如何去创建矩阵.
//Setupthecamera\'sprojectionparameters
floatfAspectRatio=pBackBufferSurfaceDesc->Width/(FLOAT)pBackBufferSurfaceDesc->Height;
g_Camera.SetProjParams(D3DX_PI/4,fAspectRatio,0.1f,5000.)0f);
g_Camera.SetWindow(pBackBufferSurfaceDesc->Width,p00BackBufferSurfaceDesc->Height);
另外,这个摄像机还封装了简单鼠标反馈.在这里,我们指定 3个鼠标按键给提供鼠标操作:模型旋转,放缩,还有摄像机旋转.试着编译工程并用每个按键体会下各个操作.
g_Camera.SetButtonMasks(MOUSE_LEFT_BUTTON,MOUSE_WHEEL,MOUSE_MIDDLE_BUTTON);
在这个按钮组基础上,摄像机会监听这些输入并产生相应效果.为了响应用户输入,需要加入个监听到MsgProc回调(DXUT消息处理).
//Passallreingwindowsmessagestocamerasoitcanrespondtouserinput
g_Camera.HandleMessages(hWnd,uMsg,wParam,lParam);
最后,在把所有数据都输入摄像机后,就是取出真正变换矩阵时候了.这里我们用相关获取投影矩阵和视图矩阵.摄像机对象会自己计算这些矩阵.
g_pProjectionVariable->SetMatrix((float*)g_Camera.GetProjMatrix);
g_pViewVariable->SetMatrix((float*)g_Camera.GetViewMatrix);
DXUT对话框
用户交互可以用CDXUTDialog来实现,它在个包含Control控件对话框里接受用户输入,并且通过句柄传递它们.首先,对话框类要例子化,然后每个单独Control控件才能加入.
声明
在这个指南里,有两个对话框会被加入,个叫g_HUD跟D3D10举例共享相同代码,另个叫g_SampleUI用于显示细节给这个指南.第 2个对话框用来控制模型"胖瘦",就是设置个变量传递给shaders.
CDXUTDialogg_HUD;//managesthe3DUI
CDXUTDialogg_SampleUI;//dialogforsamplespeciccontrols
这些对话框被CDXUTDialogResourceManager控制着.这个管理会在对话框的间传递消息并处理共享资源.
CDXUTDialogResourceManagerg_DialogResourceManager;//managerforsharedresourcesofdialogs
最后,些回调和GUI处理实际消息相关联.这个用于处理Control控件间交互.
voidCALLBACKOnGUIEvent(UINTnEvent,nControlID,CDXUTControl*pControl,void*pUserContext);
对话框
既然已经介绍了许多有用东西,那么需要被化,这个指南将这些模块真正化转移到个单独,叫InitApp.
每个对话框Control控件被化就是在这个里.每个对话框都需要,并传递给资源管理者来指定把Control控件供给谁.同样,它们设置回调来处理GUI响应.既然这样,这个相关回调是OnGUIEvent.
g_HUD.Init(&g_DialogResourceManager);
g_SampleUI.Init(&g_DialogResourceManager);
g_HUD.SetCallback(OnGUIEvent);
g_SampleUI.SetCallback(OnGUIEvent);


在它们被化后,每个都对话框可以加入它们想要使用Control控件.对话框HUD加入了3个按钮用于基本功能:切换全屏,切换引用(软件Software)渲染器,和改变设备.
要加入个按钮,你要指定你想要使用IDC标识符,个用于显示串,坐标,宽和高,还有可选和它关联热键.热键可以用键盘快速地开关这些按钮.
注意指定坐标和对话框定位相关.
iY=10;
g_HUD.AddButton(IDC_TOGGLEFULLSCREEN,L"Togglefullscreen",35,iY,125,22);
g_HUD.AddButton(IDC_TOGGLEREF,L"ToggleREF(F3)",35,iY24,125,22);
g_HUD.AddButton(IDC_CHANGEDEVICE,L"Changedevice(F2)",35,iY24,125,22,VK_F2);
同样对于sampleUI,加入了这些Control控件,个静态文本,个滑块,还有个复选按钮.
传递给静态文本参数是IDC标识符,串,坐标,和宽高.
滑块参数是IDC标识符,串,坐标,和宽高,还有滑块最大最小值,最后是存储结果变量.
复选按钮包括IDC标识符,串标签,wf坐标,宽高,还有存储结果布尔值.
iY=10;
WCHARsz[100];
iY24;
StringCchPrf(sz,100,L"Puffiness:%0.2f",g_fModelPuffiness);
g_SampleUI.AddStatic(IDC_PUFF_STATIC,sz,35,iY24,125,22);
g_SampleUI.AddSlider(IDC_PUFF_SCALE,50,iY24,100,22,0,2000,()(g_fModelPuffiness*100.0f));

iY24;
g_SampleUI.AddCheckBox(IDC_TOGGLESPIN,L"ToggleSpinning",35,iY24,125,22,g_bSpinning);
化了,这个对话框要显示在屏幕上.这个由OnD3D10ResizedSwapChain来完成既然屏幕坐标每次改变这个交换链会重建(可能由于窗口大小变化).
g_HUD.SetLocation(pBackBufferSurfaceDesc->Width-170,0);
g_HUD.SetSize(170,170);
g_SampleUI.SetLocation(pBackBufferSurfaceDesc->Width-170,pBackBufferSurfaceDesc->Height-300);
g_SampleUI.SetSize(170,300);
对话框最后步在哪需要鉴别它们自己是OnD3D10FrameRender.个对话框如果你不绘制它并且用户看不到不太好吧?
//
//RendertheUI
//
g_HUD.OnRender(fElapsedTime);
g_SampleUI.OnRender(fElapsedTime);
资源管理
资源管理在每次回调化和销毁时需要被化.这是在每次设备被重建时候GUI需被重建,或者交换链被重建时候.CDXUTDialogResourceManager类包含符合每个这样回调,具有名字.因此,它仅仅是在合适地方插入代码来它们.
V_RETURN(g_DialogResourceManager.OnD3D10CreateDevice(pd3dDevice));
V_RETURN(g_DialogResourceManager.OnD3D10ResizedSwapChain(pd3dDevice,pBackBufferSurfaceDesc));
g_DialogResourceManager.OnD3D10ReleasingSwapChain;
g_DialogResourceManager.OnD3D10DestroyDevice;
响应GUI事件
当全部化完成后,我们最后可以开始写代码来处理GUI交互了.在我们化对话框时候,我们设置这些对话框回调做为OnGUIEvent.现在我们将要创建OnGUIEvent,它会监听并处理GUI相关事件(被框架).
这是个简单对每个IDC标识符包含代码块它在对话框创建时被监听.在每个块中会是处理代码,假设用户以某种方式控制.这里处理控制代码跟Win32代码很像.
跟HUD相关控制实际上DXUT内置.有个DXUT关系到切换全屏,绑定引用软件Software渲染器,并且更改设备设置(它会下面提到3D设置对话框).
SampleUI对话框包含自定义代码操作跟滑块相关联变量.它会收集数值,更新和它相关文本,并把数值传递给滑块.
voidCALLBACKOnGUIEvent(UINTnEvent,nControlID,CDXUTControl*pControl,void*pUserContext)
{

switch(nControlID)
{
IDC_TOGGLEFULLSCREEN:DXUTToggleFullScreen;;


IDC_TOGGLEREF:DXUTToggleREF;;
IDC_CHANGEDEVICE:g_D3DSettingsDlg.SetActive(!g_D3DSettingsDlg.IsActive);;

IDC_TOGGLESPIN:
{
g_bSpinning=g_SampleUI.GetCheckBox(IDC_TOGGLESPIN)->GetChecked;
;
}

IDC_PUFF_SCALE:
{
g_fModelPuffiness=(float)(g_SampleUI.GetSlider(IDC_PUFF_SCALE)->Getvalue*0.01f);

WCHARsz[100];
StringCchPrf(sz,100,L"Puffiness:%0.2f",g_fModelPuffiness);
g_SampleUI.GetStatic(IDC_PUFF_STATIC)->SetText(sz);

g_pPuffiness->SetFloat(g_fModelPuffiness);
;
}
}

}
更新消息处理
既然现在我们有对话框消息和用户交互,那就会有传递给应用消息需要被解析,如果适用话.那些代码会在DXUT提供MsgProc回调中被处理.在的前指南里,这段是空白没有消息需要被处理.但是现在,我们要确保发送给资源管理和对话框消息被适当地发送.
不需要专门消息处理代码;我们只需要对每个对话框MsgProcs来确保消息被处理了.这通过每个单独相应MsgProc来完成.应该注意到这个提供了个标记通报给框架不需要更多处理,因此,可以退出.
LRESULTCALLBACKMsgProc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam,bool*pbNoFurtherProcessing,void*pUserContext)
{
//Alwaysallowdialogresourcemanagercallstohandleglobalmessages
//soGUIstateisupdatedcorrectly
*pbNoFurtherProcessing=g_DialogResourceManager.MsgProc(hWnd,uMsg,wParam,lParam);
(*pbNoFurtherProcessing)
0;

(g_D3DSettingsDlg.IsActive)
{
g_D3DSettingsDlg.MsgProc(hWnd,uMsg,wParam,lParam);
0;
}

//Givethedialogsachancetohandlethemessagefirst
*pbNoFurtherProcessing=g_HUD.MsgProc(hWnd,uMsg,wParam,lParam);
(*pbNoFurtherProcessing)
0;
*pbNoFurtherProcessing=g_SampleUI.MsgProc(hWnd,uMsg,wParam,lParam);
(*pbNoFurtherProcessing)


0;

(uMsgWM_CHAR&&wParam\'1\')
DXUTToggleFullScreen;

0;
}
3D设置对话框
个专门内置对话框用来控制D3DDevice设置.DXUT提供这个对话框就是CD3DSettingsDlg.它功能像个自定义对话框,但是它会提供给用户所有他们需要修改设置选项.
CD3DSettingsDlgg_D3DSettingsDlg;//Devicetingsdialog
化就像其它对话框样,你可以.然而,每次Direct3D改变它交换链或者设备,这个对话框必须被更新.因此,它必须包含在OnD3D10CreateDevice和OnD3D10ResizedSwapChain里,相对应地命名,来反映这些改变.同样地,销毁对象改变必须被通报,因而,需要在OnD3D10DestroyDevice里.
g_D3DSettingsDlg.Init(&g_DialogResourceManager);

V_RETURN(g_D3DSettingsDlg.OnD3D10CreateDevice(pd3dDevice));
V_RETURN(g_D3DSettingsDlg.OnD3D10ResizedSwapChain(pd3dDevice,pBackBufferSurfaceDesc));

g_D3DSettingsDlg.OnD3D10DestroyDevice;
在渲染边,对话框出现可以被改变,它通过个叫IsActive标记来转换.如果这个标记被设成false,那么这个面板将不会被渲染.这个面板改变是受上面说过HUD对话框处理.标记TheIDC_CHANGEDEVICE和HUDControl控件相关,就像上面提到那样.
(g_D3DSettingsDlg.IsActive)
{
g_D3DSettingsDlg.MsgProc(hWnd,uMsg,wParam,lParam);
0;
}
旦这些步骤都完成了,你就可以在你中加入这个对话框.试着编译这个指南并和更改设置面板进行交互来观察它效果.真正D3DDevice或交换链重构在DXUT内部完成.
文本渲染
不会有趣如果用户不知道干什么.所以就DXUT包含了个工具类用于在屏幕上绘制2D文本,用来给用户反馈.这个类,CDXUTD3D10TextHelper,允许你在屏幕任意位置绘制行行文本,并有简单串输入.开始的前,我们要例子化这个类.既然文本渲染和大多数化过程独立,在这个指南里我们让大部分代码在RenderText10里.
CDXUTD3D10TextHelpertxtHelper(g_pFont,g_pSprite,15);

我们传入个参数是我们要绘制字体.字体类型是D3DX提供ID3DXFont.要化这个字体,你D3DX10CreateFont,并且你要传入设备,高度,宽度,重量,mip层次(般取1),斜体,集,精度,质量,倾斜度和家族,字体名称,还有你对象指针.虽然它看起来像很多,只有开始4个和最后2个真正有意义.
V_RETURN(D3DX10CreateFont(pd3dDevice,15,0,FW_BOLD,1,FALSE,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,
L"Arial",&g_pFont));
第2个参数需要我们个ID3DXSprite类.要做这个话,我们可以D3DX10CreateSprite(noticethetrendhere?).这个只需要设备和对象指针做为参数.
//Initializethesprite
V_RETURN(D3DX10CreateSprite(pd3dDevice,&g_pSprite));
当然,像其它对象样,字体和精灵在我们完成时必须被销毁.这可以用常见SAFE_RELEASE宏完成.
SAFE_RELEASE(g_pFont);
SAFE_RELEASE(g_pSprite);
渲染
在这个举例里包含文本里有渲染统计信息.另外,还有个区域显示怎样用鼠标操作模型.
渲染必须在OnD3D10FrameRender里,而且在这个指南里,它是在帧渲染RenderText10来完成.
个区域直在绘制,因此,它最先完成.第个文本渲染是Begin.它通知引擎我要开始输出文本到屏幕.在那的后,我们设置好“指针”位置,文本颜色,我们就准备绘制了.


输出串文本要DrawTextLine来完成.你传入串,它就会在当前位置输出.它在文本书写同时增加指针,因此,如果q包含了个\\n,它会自动移动指针到下行.
//Outputstatistics
txtHelper.Begin;
txtHelper.SetInsertionPos(2,0);
txtHelper.SetForegroundColor(D3DXCOLOR(1.0f,1.0f,0.0f,1.0f));
txtHelper.DrawTextLine(DXUTGetFrameStats);
txtHelper.DrawTextLine(DXUTGetDeviceStats);
还有另个思路方法来输出文本,就好似通常使用prf.你用特殊来格式化串,然后插入变量到串里.这通过DrawFormattedTextLine来实现.
txtHelper.SetForegroundColor(D3DXCOLOR(1.0f,1.0f,1.0f,1.0f));
txtHelper.DrawFormattedTextLine(L"fTime:%0.1fsin(fTime):%0.4f",fTime,sin(fTime));
既然帮助绘制用种相似方式,所以不需要涵盖那部分代码了.定要注意你能在任何时候通过SetInsertionPos来重新设置指针位置.
最后,当你对文本输出满意后,End来通知引擎你完成了.

Feedback?Pleaseprovideuswithyourcommentsonthistopic.
Formorehelp,visittheDirectXDeveloperCenter

©2005MicrosoftCorporation.Allrightsreserved.


Tags:  c语言进阶 dxut.h

延伸阅读

最新评论

发表评论