1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include "IEditorMaterial.h"
6 #include "PreviewModelCtrl.h"
8 #include <Cry3DEngine/I3DEngine.h>
9 #include <CryEntitySystem/IEntitySystem.h>
10 #include <CryAnimation/ICryAnimation.h>
11 #include <CryRenderer/IRenderAuxGeom.h>
12 #include <CryParticleSystem/IParticles.h>
14 #include "IIconManager.h"
15 #include "ViewportInteraction.h"
16 #include <Preferences/ViewportPreferences.h>
17 #include "RenderLock.h"
19 CPreviewModelCtrl::CPreviewModelCtrl()
33 m_backgroundTextureId
= 0;
35 m_pRenderer
= GetIEditor()->GetRenderer();
36 m_pAnimationSystem
= GetIEditor()->GetSystem()->GetIAnimationSystem();
39 m_camera
.SetFrustum(800, 600, DEG2RAD(m_fov
), 0.02f
, 10000.0f
);
41 m_bInRotateMode
= false;
42 m_bInMoveMode
= false;
47 l
.m_Flags
|= DLF_SUN
| DLF_DIRECTIONAL
;
48 l
.SetLightColor(ColorF(L
, L
, L
, 1));
49 l
.SetPosition(Vec3(100, 100, 100));
51 m_lights
.push_back(l
);
53 m_bUseBacklight
= false;
54 m_renderContextCreated
= false;
55 m_bHaveAnythingToRender
= false;
59 m_bShowNormals
= false;
60 m_bShowPhysics
= false;
61 m_bShowRenderInfo
= false;
63 m_cameraAngles
.Set(0, 0, 0);
65 m_clearColor
.set(0.5f
, 0.5f
, 0.5f
, 1.0f
);
66 m_ambientColor
.set(1.0f
, 1.0f
, 1.0f
, 1.0f
);
67 m_ambientMultiplier
= 0.5f
;
69 m_cameraChangeCallback
= NULL
;
70 m_bPrecacheMaterial
= false;
71 m_bDrawWireFrame
= false;
81 GetIEditor()->RegisterNotifyListener(this);
82 m_physHelpers0
= gEnv
->pPhysicalWorld
->GetPhysVars()->iDrawHelpers
;
85 CPreviewModelCtrl::~CPreviewModelCtrl()
88 GetIEditor()->UnregisterNotifyListener(this);
89 gEnv
->pPhysicalWorld
->GetPhysVars()->iDrawHelpers
= m_physHelpers0
;
92 BEGIN_MESSAGE_MAP(CPreviewModelCtrl
, CWnd
)
93 //{{AFX_MSG_MAP(CPreviewModelCtrl)
111 BOOL
CPreviewModelCtrl::Create(CWnd
* pWndParent
, const CRect
& rc
, DWORD dwStyle
, UINT nID
)
113 BOOL bReturn
= CreateEx(NULL
, AfxRegisterWndClass(CS_DBLCLKS
| CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
,
114 AfxGetApp()->LoadStandardCursor(IDC_ARROW
), NULL
, NULL
), NULL
, dwStyle
,
115 rc
, pWndParent
, nID
, NULL
);
120 int CPreviewModelCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct
)
122 if (CWnd::OnCreate(lpCreateStruct
) == -1)
128 bool CPreviewModelCtrl::CreateRenderContext()
131 if (m_pRenderer
&& !m_renderContextCreated
)
135 IRenderer::SDisplayContextDescription desc
;
137 desc
.handle
= m_hWnd
;
138 desc
.type
= IRenderer::eViewportType_Secondary
;
139 desc
.clearColor
= m_clearColor
;
140 desc
.renderFlags
= FRT_CLEAR_COLOR
| FRT_CLEAR_DEPTH
| FRT_TEMPORARY_DEPTH
;
141 desc
.superSamplingFactor
.x
= 1;
142 desc
.superSamplingFactor
.y
= 1;
143 desc
.screenResolution
.x
= rc
.Width();
144 desc
.screenResolution
.y
= rc
.Height();
146 m_displayContextKey
= m_pRenderer
->CreateSwapChainBackedContext(desc
);
147 m_renderContextCreated
= true;
155 void CPreviewModelCtrl::DestroyRenderContext()
157 // Destroy render context.
158 if (m_pRenderer
&& m_renderContextCreated
)
160 // Do not delete primary context.
161 if (m_displayContextKey
!= reinterpret_cast<HWND
>(m_pRenderer
->GetHWND()))
162 m_pRenderer
->DeleteContext(m_displayContextKey
);
164 m_renderContextCreated
= false;
168 SDisplayContext
CPreviewModelCtrl::InitDisplayContext(const SDisplayContextKey
& displayContextKey
)
170 CRY_PROFILE_FUNCTION(PROFILE_EDITOR
);
172 SDisplayContext dctx
;
173 dctx
.SetDisplayContext(displayContextKey
, IRenderer::eViewportType_Secondary
);
174 // dctx.SetView(m_pViewportAdapter.get());
175 dctx
.SetCamera(&m_camera
);
176 dctx
.renderer
= m_pRenderer
;
177 dctx
.engine
= nullptr;
178 dctx
.box
.min
= Vec3(-100000, -100000, -100000);
179 dctx
.box
.max
= Vec3(100000, 100000, 100000);
185 void CPreviewModelCtrl::PreSubclassWindow()
187 CWnd::PreSubclassWindow();
190 void CPreviewModelCtrl::ReleaseObject()
193 SAFE_RELEASE(m_pCharacter
);
196 m_pEmitter
->Activate(false);
197 m_pEmitter
->Release();
201 m_bHaveAnythingToRender
= false;
204 void CPreviewModelCtrl::LoadFile(const char* modelFile
, bool changeCamera
)
206 m_bHaveAnythingToRender
= false;
214 if (!modelFile
|| !*modelFile
)
223 m_loadedFile
= modelFile
;
225 CString strFileExt
= PathUtil::GetExt(modelFile
);
226 uint32 isSKEL
= stricmp(strFileExt
, CRY_SKEL_FILE_EXT
) == 0;
227 uint32 isSKIN
= stricmp(strFileExt
, CRY_SKIN_FILE_EXT
) == 0;
228 uint32 isCDF
= stricmp(strFileExt
, CRY_CHARACTER_DEFINITION_FILE_EXT
) == 0;
229 uint32 isCGA
= stricmp(strFileExt
, CRY_ANIM_GEOMETRY_FILE_EXT
) == 0;
230 uint32 isCGF
= stricmp(strFileExt
, CRY_GEOMETRY_FILE_EXT
) == 0;
234 // Load CGA animated object.
235 m_pCharacter
= m_pAnimationSystem
->CreateInstance(modelFile
);
238 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_WARNING
, "Loading of geometry object %s failed.", modelFile
);
245 m_pCharacter
->AddRef();
246 m_aabb
= m_pCharacter
->GetAABB();
249 if (isSKEL
|| isSKIN
|| isCDF
)
252 m_pCharacter
= m_pAnimationSystem
->CreateInstance(modelFile
, CA_PreviewMode
| CA_CharEditModel
);
255 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_WARNING
, "Loading of character %s failed.", modelFile
);
262 m_pCharacter
->AddRef();
263 m_aabb
= m_pCharacter
->GetAABB();
269 m_pObj
= GetIEditor()->Get3DEngine()->LoadStatObj(modelFile
, NULL
, NULL
, false);
272 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_WARNING
, "Loading of geometry object %s failed.", (const char*)modelFile
);
279 m_aabb
.min
= m_pObj
->GetBoxMin();
280 m_aabb
.max
= m_pObj
->GetBoxMax();
291 m_bHaveAnythingToRender
= true;
299 void CPreviewModelCtrl::LoadParticleEffect(IParticleEffect
* pEffect
)
301 m_bHaveAnythingToRender
= false;
314 if (rc
.bottom
- rc
.top
< 2 || rc
.right
- rc
.left
< 2)
319 tm
.SetRotationXYZ(Ang3(DEG2RAD(90.0f
), 0, 0));
321 m_bHaveAnythingToRender
= true;
324 m_pEmitter
= pEffect
->Spawn(tm
, sp
);
327 m_pEmitter
->AddRef();
328 m_pEmitter
->Update();
329 m_aabb
= m_pEmitter
->GetBBox();
330 if (m_aabb
.IsReset())
338 void CPreviewModelCtrl::SetEntity(IRenderNode
* entity
)
340 m_bHaveAnythingToRender
= false;
341 if (m_pEntity
!= entity
)
346 m_bHaveAnythingToRender
= true;
347 m_aabb
= m_pEntity
->GetBBox();
353 void CPreviewModelCtrl::SetObject(IStatObj
* pObject
)
355 if (m_pObj
!= pObject
)
357 m_bHaveAnythingToRender
= false;
361 m_bHaveAnythingToRender
= true;
362 m_aabb
= m_pObj
->GetAABB();
368 void CPreviewModelCtrl::SetCameraRadius(float fRadius
)
370 m_cameraRadius
= fRadius
;
372 Matrix34 m
= m_camera
.GetMatrix();
373 Vec3 dir
= m
.TransformVector(Vec3(0, 1, 0));
374 Matrix34 tm
= Matrix33::CreateRotationVDir(dir
, 0);
375 tm
.SetTranslation(m_cameraTarget
- dir
* m_cameraRadius
);
376 m_camera
.SetMatrix(tm
);
377 if (m_cameraChangeCallback
)
378 m_cameraChangeCallback(m_pCameraChangeUserData
, this);
381 void CPreviewModelCtrl::SetCameraLookAt(float fRadiusScale
, const Vec3
& fromDir
)
383 m_cameraTarget
= m_aabb
.GetCenter();
384 m_cameraRadius
= m_aabb
.GetRadius() * fRadiusScale
;
386 Vec3 dir
= fromDir
.GetNormalized();
387 Matrix34 tm
= Matrix33::CreateRotationVDir(dir
, 0);
388 tm
.SetTranslation(m_cameraTarget
- dir
* m_cameraRadius
);
389 m_camera
.SetMatrix(tm
);
390 if (m_cameraChangeCallback
)
391 m_cameraChangeCallback(m_pCameraChangeUserData
, this);
394 CCamera
& CPreviewModelCtrl::GetCamera()
399 void CPreviewModelCtrl::UseBackLight(bool bEnable
)
405 l
.m_Flags
|= DLF_POINT
;
406 l
.SetPosition(Vec3(-100, 100, -100));
408 l
.SetLightColor(ColorF(L
, L
, L
, 1));
410 m_lights
.push_back(l
);
416 m_bUseBacklight
= bEnable
;
419 void CPreviewModelCtrl::OnPaint()
426 // Get the rect of the client window
427 GetClientRect(&rect
);
430 cFillBrush
.CreateSolidBrush(RGB(128, 128, 128));
431 // Fill the entire client area
432 dc
.FillRect(&rect
, &cFillBrush
);
436 BOOL
CPreviewModelCtrl::OnEraseBkgnd(CDC
* pDC
)
438 if (m_bHaveAnythingToRender
)
441 return CWnd::OnEraseBkgnd(pDC
);
444 void CPreviewModelCtrl::SetCamera(CCamera
& cam
)
446 m_camera
.SetPosition(cam
.GetPosition());
450 int w
= rc
.Width() * m_tileSizeX
;
451 int h
= rc
.Height() * m_tileSizeY
;
452 m_camera
.SetFrustum(w
, h
, DEG2RAD(m_fov
), m_camera
.GetNearPlane(), m_camera
.GetFarPlane());
454 if (m_cameraChangeCallback
)
455 m_cameraChangeCallback(m_pCameraChangeUserData
, this);
458 void CPreviewModelCtrl::SetOrbitAngles(const Ang3
& ang
)
463 bool CPreviewModelCtrl::Render()
467 // lock while we are rendering to prevent any recursive rendering across the application
468 if (CScopedRenderLock lock
= CScopedRenderLock())
470 if (!m_renderContextCreated
)
472 if (!CreateRenderContext())
476 // Configures Aux to draw to the current display-context
477 SDisplayContext context
= InitDisplayContext(m_displayContextKey
);
479 m_pRenderer
->BeginFrame(m_displayContextKey
);
481 result
= RenderInternal(context
);
483 m_pRenderer
->EndFrame();
489 bool CPreviewModelCtrl::RenderInternal(SDisplayContext
& context
)
494 int width
= rc
.right
- rc
.left
;
495 int height
= rc
.bottom
- rc
.top
;
496 if (height
< 2 || width
< 2)
502 if (m_bGrid
|| m_bAxis
)
506 int showNormals
= gEnv
->pConsole
->GetCVar("r_ShowNormals")->GetIVal();
507 int showPhysics
= gEnv
->pConsole
->GetCVar("p_draw_helpers")->GetIVal();
508 int showInfo
= gEnv
->pConsole
->GetCVar("r_displayInfo")->GetIVal();
510 gEnv
->pConsole
->GetCVar("r_ShowNormals")->Set((int)m_bShowNormals
);
511 gEnv
->pConsole
->GetCVar("p_draw_helpers")->Set((int)m_bShowPhysics
);
512 gEnv
->pConsole
->GetCVar("r_displayInfo")->Set((int)m_bShowRenderInfo
);
515 SRenderingPassInfo passInfo
= SRenderingPassInfo::CreateGeneralPassRenderingInfo(m_camera
, SRenderingPassInfo::DEFAULT_FLAGS
, true, context
.GetDisplayContextKey());
516 passInfo
.GetIRenderView()->SetShaderRenderingFlags(SHDF_NOASYNC
| SHDF_ALLOWHDR
| SHDF_SECONDARY_VIEWPORT
);
517 m_pRenderer
->EF_StartEf(passInfo
);
520 CScopedWireFrameMode
scopedWireFrame(m_pRenderer
, m_bDrawWireFrame
? R_WIREFRAME_MODE
: R_SOLID_MODE
);
523 for (size_t i
= 0; i
< m_lights
.size(); i
++)
525 m_pRenderer
->EF_ADDDlight(&m_lights
[i
], passInfo
);
528 if (m_pCurrentMaterial
)
529 m_pCurrentMaterial
->DisableHighlight();
531 _smart_ptr
<IMaterial
> pMaterial
;
532 if (m_pCurrentMaterial
)
533 pMaterial
= m_pCurrentMaterial
->GetMatInfo();
535 if (m_bPrecacheMaterial
)
537 IMaterial
* pCurMat
= pMaterial
;
541 pCurMat
= m_pObj
->GetMaterial();
543 pCurMat
= m_pEntity
->GetMaterial();
544 else if (m_pCharacter
)
545 pCurMat
= m_pCharacter
->GetIMaterial();
547 pCurMat
= m_pEmitter
->GetMaterial();
551 pCurMat
->PrecacheMaterial(0.0f
, NULL
, true, true);
556 // activate shader item
557 IMaterial
* pCurMat
= pMaterial
;
561 pCurMat
= m_pObj
->GetMaterial();
563 pCurMat
= m_pEntity
->GetMaterial();
564 else if (m_pCharacter
)
565 pCurMat
= m_pCharacter
->GetIMaterial();
567 pCurMat
= m_pEmitter
->GetMaterial();
571 pCurMat->ActivateAllShaderItem();
576 RenderObject(pMaterial
, passInfo
);
578 m_pRenderer
->EF_EndEf3D(-1, -1, passInfo
);
581 RenderEffect(pMaterial
, passInfo
);
584 m_pRenderer
->RenderDebug(false);
586 gEnv
->pConsole
->GetCVar("r_ShowNormals")->Set(showNormals
);
587 gEnv
->pConsole
->GetCVar("p_draw_helpers")->Set(showPhysics
);
588 gEnv
->pConsole
->GetCVar("r_displayInfo")->Set(showInfo
);
593 void CPreviewModelCtrl::RenderObject(IMaterial
* pMaterial
, const SRenderingPassInfo
& passInfo
)
597 rp
.AmbientColor
= m_ambientColor
* m_ambientMultiplier
;
598 rp
.dwFObjFlags
|= FOB_TRANS_MASK
/*| FOB_GLOBAL_ILLUMINATION*/ | FOB_NO_FOG
/*| FOB_ZPREPASS*/;
599 rp
.pMaterial
= pMaterial
;
607 tm
.SetRotationXYZ(Ang3(0, 0, m_rotateAngle
));
608 m_rotateAngle
+= 0.1f
;
612 m_pObj
->Render(rp
, passInfo
);
615 m_pEntity
->Render(rp
, passInfo
);
618 m_pCharacter
->Render(rp
, passInfo
);
622 m_pEmitter
->Update();
623 m_pEmitter
->Render(rp
, passInfo
);
627 void CPreviewModelCtrl::RenderEffect(IMaterial
* pMaterial
, const SRenderingPassInfo
& passInfo
)
631 void CPreviewModelCtrl::DrawGrid()
638 IRenderAuxGeom
* pRag
= m_pRenderer
->GetIRenderAuxGeom();
639 SAuxGeomRenderFlags nRendFlags
= pRag
->GetRenderFlags();
641 pRag
->SetRenderFlags(e_Def3DPublicRenderflags
);
642 SAuxGeomRenderFlags nNewFlags
= pRag
->GetRenderFlags();
643 nNewFlags
.SetAlphaBlendMode(e_AlphaBlended
);
644 pRag
->SetRenderFlags(nNewFlags
);
650 for (float x
= -XR
; x
< XR
; x
+= step
)
653 pRag
->DrawLine(Vec3(x
, -YR
, 0), ColorB(150, 150, 150, nGridAlpha
), Vec3(x
, YR
, 0), ColorB(150, 150, 150, nGridAlpha
));
655 for (float y
= -YR
; y
< YR
; y
+= step
)
658 pRag
->DrawLine(Vec3(-XR
, y
, 0), ColorB(150, 150, 150, nGridAlpha
), Vec3(XR
, y
, 0), ColorB(150, 150, 150, nGridAlpha
));
667 pRag
->DrawLine(Vec3(0, 0, 0), ColorB(255, 0, 0, nGridAlpha
), Vec3(XR
, 0, 0), ColorB(255, 0, 0, nGridAlpha
));
668 pRag
->DrawLine(Vec3(0, 0, 0), ColorB(0, 255, 0, nGridAlpha
), Vec3(0, YR
, 0), ColorB(0, 255, 0, nGridAlpha
));
669 pRag
->DrawLine(Vec3(0, 0, 0), ColorB(0, 0, 255, nGridAlpha
), Vec3(0, 0, YR
), ColorB(0, 0, 255, nGridAlpha
));
671 pRag
->SetRenderFlags(nRendFlags
);
674 void CPreviewModelCtrl::UpdateAnimation()
678 GetISystem()->GetIAnimationSystem()->Update(false);
679 m_pCharacter
->GetISkeletonPose()->SetForceSkeletonUpdate(0);
681 const CCamera
& camera
= GetCamera();
682 float fDistance
= (camera
.GetPosition()).GetLength();
683 float fZoomFactor
= 0.001f
+ 0.999f
* (RAD2DEG(camera
.GetFov()) / 60.f
);
685 SAnimationProcessParams params
;
686 params
.locationAnimation
= QuatTS(IDENTITY
);
687 params
.bOnRender
= 0;
688 params
.zoomAdjustedDistanceFromCamera
= fDistance
* fZoomFactor
;
689 m_pCharacter
->StartAnimationProcessing(params
);
690 m_pCharacter
->FinishAnimationComputations();
692 m_aabb
= m_pCharacter
->GetAABB();
696 void CPreviewModelCtrl::OnTimer(UINT_PTR nIDEvent
)
698 if (IsWindowVisible())
700 if (m_bHaveAnythingToRender
)
704 CWnd::OnTimer(nIDEvent
);
707 void CPreviewModelCtrl::SetCameraTM(const Matrix34
& cameraTM
)
709 m_camera
.SetMatrix(cameraTM
);
710 if (m_cameraChangeCallback
)
711 m_cameraChangeCallback(m_pCameraChangeUserData
, this);
714 void CPreviewModelCtrl::GetCameraTM(Matrix34
& cameraTM
)
716 cameraTM
= m_camera
.GetMatrix();
719 void CPreviewModelCtrl::OnDestroy()
722 DestroyRenderContext();
730 void CPreviewModelCtrl::OnLButtonDown(UINT nFlags
, CPoint point
)
732 m_bInRotateMode
= true;
733 m_mousePosition
= point
;
740 void CPreviewModelCtrl::OnLButtonUp(UINT nFlags
, CPoint point
)
742 m_bInRotateMode
= false;
748 void CPreviewModelCtrl::OnMButtonDown(UINT nFlags
, CPoint point
)
750 m_bInRotateMode
= true;
751 m_bInMoveMode
= true;
752 m_mousePosition
= point
;
757 void CPreviewModelCtrl::OnMButtonUp(UINT nFlags
, CPoint point
)
759 m_bInRotateMode
= false;
760 m_bInMoveMode
= false;
765 void CPreviewModelCtrl::OnMouseMove(UINT nFlags
, CPoint point
)
767 // TODO: Add your message handler code here and/or call default
768 CWnd::OnMouseMove(nFlags
, point
);
770 if (point
== m_mousePosition
)
776 Matrix34 m
= m_camera
.GetMatrix();
778 Vec3 zdir
= m
.GetColumn1().GetNormalized();
781 float dx
= (point
.x
- m_mousePosition
.x
);
782 float dy
= (point
.y
- m_mousePosition
.y
);
783 m_camera
.SetPosition(m_camera
.GetPosition() + step
* xdir
* dx
+ step
* zdir
* dy
);
786 CPoint pnt
= m_mousePosition
;
787 ClientToScreen(&pnt
);
788 SetCursorPos(pnt
.x
, pnt
.y
);
791 else if (m_bInRotateMode
)
793 Vec3 pos
= m_camera
.GetMatrix().GetTranslation();
794 m_cameraRadius
= Vec3(m_camera
.GetMatrix().GetTranslation() - m_cameraTarget
).GetLength();
796 Ang3
angles(-point
.y
+ m_mousePosition
.y
, 0, -point
.x
+ m_mousePosition
.x
);
797 angles
= angles
* 0.002f
;
799 Matrix34 camtm
= m_camera
.GetMatrix();
800 Matrix33 Rz
= Matrix33::CreateRotationXYZ(Ang3(0, 0, angles
.z
)); // Rotate around vertical axis.
801 Matrix33 Rx
= Matrix33::CreateRotationAA(angles
.x
, camtm
.GetColumn0()); // Rotate with angle around x axis in camera space.
803 Vec3 dir
= camtm
.TransformVector(Vec3(0, 1, 0));
804 Vec3 newdir
= (Rx
* Rz
).TransformVector(dir
).GetNormalized();
805 camtm
= Matrix34(Matrix33::CreateRotationVDir(newdir
, 0), m_cameraTarget
- newdir
* m_cameraRadius
);
806 m_camera
.SetMatrix(camtm
);
807 if (m_cameraChangeCallback
)
808 m_cameraChangeCallback(m_pCameraChangeUserData
, this);
810 CPoint pnt
= m_mousePosition
;
811 ClientToScreen(&pnt
);
812 SetCursorPos(pnt
.x
, pnt
.y
);
815 else if (m_bInMoveMode
)
818 float speedScale
= 0.001f
;
819 Matrix34 m
= m_camera
.GetMatrix();
820 Vec3 xdir
= m
.GetColumn0().GetNormalized();
821 Vec3 zdir
= m
.GetColumn2().GetNormalized();
823 Vec3 pos
= m_cameraTarget
;
824 pos
+= 0.1f
* xdir
* (point
.x
- m_mousePosition
.x
) * speedScale
+ 0.1f
* zdir
* (m_mousePosition
.y
- point
.y
) * speedScale
;
825 m_cameraTarget
= pos
;
827 Vec3 dir
= m
.TransformVector(Vec3(0, 1, 0));
828 m
.SetTranslation(m_cameraTarget
- dir
* m_cameraRadius
);
829 m_camera
.SetMatrix(m
);
830 if (m_cameraChangeCallback
)
831 m_cameraChangeCallback(m_pCameraChangeUserData
, this);
833 m_mousePosition
= point
;
834 CPoint pnt
= m_mousePosition
;
835 ClientToScreen(&pnt
);
836 SetCursorPos(pnt
.x
, pnt
.y
);
841 void CPreviewModelCtrl::OnRButtonDown(UINT nFlags
, CPoint point
)
843 m_bInMoveMode
= true;
844 m_mousePosition
= point
;
845 if (!m_bInRotateMode
)
850 void CPreviewModelCtrl::OnRButtonUp(UINT nFlags
, CPoint point
)
852 m_bInMoveMode
= false;
853 m_mousePosition
= point
;
854 if (!m_bInRotateMode
)
859 BOOL
CPreviewModelCtrl::OnMouseWheel(UINT nFlags
, short zDelta
, CPoint point
)
861 // TODO: Add your message handler code here and/or call default
862 Matrix34 m
= m_camera
.GetMatrix();
863 Vec3 zdir
= m
.GetColumn1().GetNormalized();
865 //m_camera.SetPosition( m_camera.GetPos() + ydir*(m_mousePos.y-point.y),xdir*(m_mousePos.x-point.x) );
866 m_camera
.SetPosition(m_camera
.GetPosition() + 0.002f
* zdir
* (zDelta
));
873 void CPreviewModelCtrl::OnSize(UINT nType
, int cx
, int cy
)
875 CWnd::OnSize(nType
, cx
, cy
);
878 //m_pRenderer->ResizeContext(GetSafeHwnd(),cx,cy);
881 void CPreviewModelCtrl::EnableUpdate(bool bUpdate
)
886 void CPreviewModelCtrl::Update(bool bForceUpdate
)
890 if (m_bUpdate
&& m_bHaveAnythingToRender
|| bForceUpdate
)
892 if (IsWindowVisible())
897 void CPreviewModelCtrl::SetRotation(bool bEnable
)
902 void CPreviewModelCtrl::SetMaterial(IEditorMaterial
* pMaterial
)
906 if ((pMaterial
->GetFlags() & MTL_FLAG_NOPREVIEW
))
908 m_pCurrentMaterial
= 0;
913 m_pCurrentMaterial
= pMaterial
;
917 IEditorMaterial
* CPreviewModelCtrl::GetMaterial()
919 return m_pCurrentMaterial
;
922 void CPreviewModelCtrl::OnEditorNotifyEvent(EEditorNotifyEvent event
)
926 case eNotify_OnIdleUpdate
:
929 case eNotify_OnClearLevelContents
:
935 void CPreviewModelCtrl::GetImageOffscreen(CImageEx
& image
, const CSize
& customSize
)
937 m_pRenderer
->EnableSwapBuffers(false);
939 m_pRenderer
->EnableSwapBuffers(true);
947 if (customSize
.cx
== 0 && customSize
.cy
== 0)
950 height
= rc
.Height();
954 width
= customSize
.cx
;
955 height
= customSize
.cy
;
958 image
.Allocate(width
, height
);
959 m_pRenderer
->ReadFrameBuffer(image
.GetData(), width
, height
);
961 // At this point the image is upside-down, so we need to flip it.
962 unsigned int* data
= image
.GetData();
963 for (int row
= 0; row
< (height
- 1) / 2; ++row
)
965 for (int col
= 0; col
< width
; ++col
)
967 unsigned int pixelUp
= data
[row
* width
+ col
];
968 unsigned int pixelDn
= data
[(height
- row
- 1) * width
+ col
];
970 data
[row
* width
+ col
] = pixelDn
;
971 data
[(height
- row
- 1) * width
+ col
] = pixelUp
;
976 void CPreviewModelCtrl::GetImage(CImageEx
& image
)
982 int width
= rc
.Width();
983 int height
= rc
.Height();
984 image
.Allocate(width
, height
);
989 dcMemory
.CreateCompatibleDC(pDC
);
991 bmp
.CreateCompatibleBitmap(pDC
, width
, height
);
993 CBitmap
* pOldBitmap
= dcMemory
.SelectObject(&bmp
);
994 dcMemory
.BitBlt(0, 0, width
, height
, pDC
, 0, 0, SRCCOPY
);
997 bmp
.GetBitmap(&bmpInfo
);
998 bmp
.GetBitmapBits(width
* height
* (bmpInfo
.bmBitsPixel
/ 8), image
.GetData());
999 int bpp
= bmpInfo
.bmBitsPixel
/ 8;
1001 dcMemory
.SelectObject(pOldBitmap
);
1006 void CPreviewModelCtrl::SetClearColor(const ColorF
& color
)
1008 m_clearColor
= color
;
1011 static int GetFaceCountRecursively(IStatObj
* p
)
1018 if (p
->GetRenderMesh())
1020 n
+= p
->GetRenderMesh()->GetIndicesCount() / 3;
1022 for (int i
= 0; i
< p
->GetSubObjectCount(); ++i
)
1024 IStatObj::SSubObject
* const pS
= p
->GetSubObject(i
);
1027 n
+= GetFaceCountRecursively(pS
->pStatObj
);
1033 static int GetVertexCountRecursively(IStatObj
* p
)
1040 if (p
->GetRenderMesh())
1042 n
+= p
->GetRenderMesh()->GetVerticesCount();
1044 for (int i
= 0; i
< p
->GetSubObjectCount(); ++i
)
1046 IStatObj::SSubObject
* const pS
= p
->GetSubObject(i
);
1049 n
+= GetVertexCountRecursively(pS
->pStatObj
);
1055 static int GetMaxLodRecursively(IStatObj
* p
)
1062 for (int i
= 1; i
< 10; i
++)
1064 if (p
->GetLodObject(i
))
1069 for (int i
= 0; i
< p
->GetSubObjectCount(); ++i
)
1071 IStatObj::SSubObject
* const pS
= p
->GetSubObject(i
);
1074 const int n2
= GetMaxLodRecursively(pS
->pStatObj
);
1075 n
= (n
< n2
) ? n2
: n
;
1088 MaterialId(const void* a_ptr
, int a_id
)
1094 bool operator<(const MaterialId
& a
) const
1096 return ptr
< a
.ptr
|| id
< a
.id
;
1101 static void CollectMaterialsRecursively(std::set
<MaterialId
>& mats
, IStatObj
* p
)
1107 if (p
->GetRenderMesh())
1109 TRenderChunkArray
& ch
= p
->GetRenderMesh()->GetChunks();
1110 for (size_t i
= 0; i
< ch
.size(); ++i
)
1112 mats
.insert(MaterialId(p
->GetMaterial(), ch
[i
].m_nMatID
));
1115 for (int i
= 0; i
< p
->GetSubObjectCount(); ++i
)
1117 IStatObj::SSubObject
* const pS
= p
->GetSubObject(i
);
1120 CollectMaterialsRecursively(mats
, pS
->pStatObj
);
1125 int CPreviewModelCtrl::GetFaceCount()
1129 return GetFaceCountRecursively(m_pObj
);
1131 else if (m_pCharacter
)
1138 int CPreviewModelCtrl::GetVertexCount()
1142 return GetVertexCountRecursively(m_pObj
);
1144 else if (m_pCharacter
)
1151 int CPreviewModelCtrl::GetMaxLod()
1155 return GetMaxLodRecursively(m_pObj
);
1157 else if (m_pCharacter
)
1159 return 1; //BaseModels have only 1 LOD
1164 int CPreviewModelCtrl::GetMtlCount()
1168 std::set
<MaterialId
> mats
;
1169 CollectMaterialsRecursively(mats
, m_pObj
);
1170 return (int)mats
.size();
1175 void CPreviewModelCtrl::FitToScreen()
1177 SetCameraLookAt(2.0f
, Vec3(1, 1, -0.5));
1180 bool CPreviewModelCtrl::CheckVirtualKey(int virtualKey
)
1182 GetAsyncKeyState(virtualKey
);
1183 if (GetAsyncKeyState(virtualKey
) & (1 << 15))
1188 void CPreviewModelCtrl::ProcessKeys()
1190 if (GetFocus() != this)
1195 Matrix34 m
= m_camera
.GetMatrix();
1197 Vec3 ydir
= m
.GetColumn2().GetNormalized();
1198 Vec3 xdir
= m
.GetColumn0().GetNormalized();
1200 Vec3 pos
= m
.GetTranslation();
1202 float speedScale
= 60.0f
* GetIEditor()->GetSystem()->GetITimer()->GetFrameTime();
1203 if (speedScale
> 20) speedScale
= 20;
1205 speedScale
*= 0.04f
;
1207 if (CheckVirtualKey(VK_SHIFT
))
1209 speedScale
*= gViewportMovementPreferences
.camFastMoveSpeed
;
1212 if (ViewportInteraction::CheckPolledKey(ViewportInteraction::eKey_Forward
))
1215 m_camera
.SetPosition(pos
+ speedScale
* moveSpeed
* ydir
);
1216 SetCamera(m_camera
);
1219 if (ViewportInteraction::CheckPolledKey(ViewportInteraction::eKey_Backward
))
1222 m_camera
.SetPosition(pos
- speedScale
* moveSpeed
* ydir
);
1223 SetCamera(m_camera
);
1227 BOOL
CPreviewModelCtrl::PreTranslateMessage(MSG
* pMsg
)
1229 if (WM_KEYDOWN
== pMsg
->message
|| WM_KEYUP
== pMsg
->message
)
1232 return CWnd::PreTranslateMessage(pMsg
);
1235 void CPreviewModelCtrl::SetBackgroundTexture(const CString
& textureFilename
)
1237 m_backgroundTextureId
= GetIEditor()->GetIconManager()->GetIconTexture(textureFilename
);
1240 void CPreviewModelCtrl::DrawBackground()
1242 if (!m_backgroundTextureId
)
1245 SVF_P3F_C4B_T2F tempVertices
[6];
1246 SVF_P3F_C4B_T2F
* pVertex
= tempVertices
;
1248 const float xpos
= 0.0f
;
1249 const float ypos
= 0.0f
;
1250 const float z
= 0.0f
;
1251 const uint32 color
= 0xFFFFFFFF;
1252 const float w
= 1.0f
;
1253 const float h
= 1.0f
;
1254 const float s
[4] = { 0.0f
, 1.0f
, 1.0f
, 0.0f
};
1255 const float t
[4] = { 1.0f
, 1.0f
, 0.0f
, 0.0f
};
1257 pVertex
->xyz
.x
= xpos
;
1258 pVertex
->xyz
.y
= ypos
;
1260 pVertex
->st
= Vec2(s
[0], t
[0]);
1261 pVertex
->color
.dcolor
= color
;
1265 pVertex
->xyz
.x
= xpos
+ w
;
1266 pVertex
->xyz
.y
= ypos
;
1268 pVertex
->st
= Vec2(s
[1], t
[1]);
1269 pVertex
->color
.dcolor
= color
;
1273 pVertex
->xyz
.x
= xpos
;
1274 pVertex
->xyz
.y
= ypos
+ h
;
1276 pVertex
->st
= Vec2(s
[3], t
[3]);
1277 pVertex
->color
.dcolor
= color
;
1281 pVertex
->xyz
.x
= xpos
;
1282 pVertex
->xyz
.y
= ypos
+ h
;
1284 pVertex
->st
= Vec2(s
[3], t
[3]);
1285 pVertex
->color
.dcolor
= color
;
1289 pVertex
->xyz
.x
= xpos
+ w
;
1290 pVertex
->xyz
.y
= ypos
;
1292 pVertex
->st
= Vec2(s
[1], t
[1]);
1293 pVertex
->color
.dcolor
= color
;
1297 pVertex
->xyz
.x
= xpos
+ w
;
1298 pVertex
->xyz
.y
= ypos
+ h
;
1300 pVertex
->st
= Vec2(s
[2], t
[2]);
1301 pVertex
->color
.dcolor
= color
;
1303 SAuxGeomRenderFlags renderFlags
;
1304 renderFlags
.SetMode2D3DFlag(e_Mode2D
);
1305 renderFlags
.SetAlphaBlendMode(e_AlphaNone
);
1306 renderFlags
.SetDrawInFrontMode(e_DrawInFrontOff
);
1307 renderFlags
.SetFillMode(e_FillModeSolid
);
1308 renderFlags
.SetCullMode(e_CullModeNone
);
1309 renderFlags
.SetDepthWriteFlag(e_DepthWriteOff
);
1310 renderFlags
.SetDepthTestFlag(e_DepthTestOff
);
1312 IRenderAuxGeom
* aux
= gEnv
->pRenderer
->GetIRenderAuxGeom();
1313 const SAuxGeomRenderFlags prevRenderFlags
= aux
->GetRenderFlags();
1314 aux
->SetRenderFlags(renderFlags
);
1315 aux
->SetTexture(m_backgroundTextureId
);
1317 aux
->DrawBuffer(tempVertices
, 6, true);
1319 aux
->SetTexture(-1);
1320 aux
->SetRenderFlags(prevRenderFlags
);