AtomDebugDisplayViewportInterface.cpp 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Serialization/SerializeContext.h>
  9. #include <AzCore/Component/ComponentApplicationBus.h>
  10. #include <AzCore/std/algorithm.h>
  11. #include <AzCore/std/containers/array.h>
  12. #include <AzCore/std/containers/span.h>
  13. #include <AzCore/Math/Obb.h>
  14. #include <AzCore/Math/Aabb.h>
  15. #include <AzCore/Math/Frustum.h>
  16. #include <AtomDebugDisplayViewportInterface.h>
  17. #include <Atom/RPI.Public/View.h>
  18. #include <Atom/RPI.Public/ViewportContextBus.h>
  19. #include <AzCore/Interface/Interface.h>
  20. #include <AzFramework/Font/FontInterface.h>
  21. namespace // unnamed namespace to hold copies of Cry AuxGeom state enum's, this is to avoid creating a dependency on IRenderAuxGeom.h
  22. {
  23. // Notes:
  24. // Don't change the xxxShift values, they need to match the values from legacy cry rendering
  25. // This also applies to the individual flags in EAuxGeomPublicRenderflags_*!
  26. // Remarks:
  27. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  28. // Check RenderAuxGeom.h in ../RenderDll/Common
  29. enum EAuxGeomPublicRenderflagBitMasks
  30. {
  31. e_Mode2D3DShift = 31,
  32. e_Mode2D3DMask = 0x1 << e_Mode2D3DShift,
  33. e_AlphaBlendingShift = 29,
  34. e_AlphaBlendingMask = 0x3 << e_AlphaBlendingShift,
  35. e_DrawInFrontShift = 28,
  36. e_DrawInFrontMask = 0x1 << e_DrawInFrontShift,
  37. e_FillModeShift = 26,
  38. e_FillModeMask = 0x3 << e_FillModeShift,
  39. e_CullModeShift = 24,
  40. e_CullModeMask = 0x3 << e_CullModeShift,
  41. e_DepthWriteShift = 23,
  42. e_DepthWriteMask = 0x1 << e_DepthWriteShift,
  43. e_DepthTestShift = 22,
  44. e_DepthTestMask = 0x1 << e_DepthTestShift,
  45. e_PublicParamsMask = e_Mode2D3DMask | e_AlphaBlendingMask | e_DrawInFrontMask | e_FillModeMask |
  46. e_CullModeMask | e_DepthWriteMask | e_DepthTestMask
  47. };
  48. // Notes:
  49. // e_Mode2D renders in normalized [0.. 1] screen space.
  50. // Don't change the xxxShift values blindly as they affect the rendering output
  51. // that is two primitives have to be rendered after 3d primitives, alpha blended
  52. // geometry have to be rendered after opaque ones, etc.
  53. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  54. // Remarks:
  55. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  56. // Check RenderAuxGeom.h in ../RenderDll/Common
  57. // See also:
  58. // EAuxGeomPublicRenderflagBitMasks
  59. enum EAuxGeomPublicRenderflags_Mode2D3D
  60. {
  61. e_Mode3D = 0x0 << e_Mode2D3DShift,
  62. e_Mode2D = 0x1 << e_Mode2D3DShift,
  63. };
  64. // Notes:
  65. // Don't change the xxxShift values blindly as they affect the rendering output
  66. // that is two primitives have to be rendered after 3d primitives, alpha blended
  67. // geometry have to be rendered after opaque ones, etc.
  68. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  69. // Remarks:
  70. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  71. // Check RenderAuxGeom.h in ../RenderDll/Common
  72. // See also:
  73. // EAuxGeomPublicRenderflagBitMasks
  74. enum EAuxGeomPublicRenderflags_AlphaBlendMode
  75. {
  76. e_AlphaNone = 0x0 << e_AlphaBlendingShift,
  77. e_AlphaAdditive = 0x1 << e_AlphaBlendingShift,
  78. e_AlphaBlended = 0x2 << e_AlphaBlendingShift,
  79. };
  80. // Notes:
  81. // Don't change the xxxShift values blindly as they affect the rendering output
  82. // that is two primitives have to be rendered after 3d primitives, alpha blended
  83. // geometry have to be rendered after opaque ones, etc.
  84. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  85. // Remarks:
  86. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  87. // Check RenderAuxGeom.h in ../RenderDll/Common
  88. // See also:
  89. // EAuxGeomPublicRenderflagBitMasks
  90. enum EAuxGeomPublicRenderflags_DrawInFrontMode
  91. {
  92. e_DrawInFrontOff = 0x0 << e_DrawInFrontShift,
  93. e_DrawInFrontOn = 0x1 << e_DrawInFrontShift,
  94. };
  95. // Notes:
  96. // Don't change the xxxShift values blindly as they affect the rendering output
  97. // that is two primitives have to be rendered after 3d primitives, alpha blended
  98. // geometry have to be rendered after opaque ones, etc.
  99. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  100. // Remarks:
  101. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  102. // Check RenderAuxGeom.h in ../RenderDll/Common
  103. // See also:
  104. // EAuxGeomPublicRenderflagBitMasks
  105. enum EAuxGeomPublicRenderflags_FillMode
  106. {
  107. e_FillModeSolid = 0x0 << e_FillModeShift,
  108. e_FillModeWireframe = 0x1 << e_FillModeShift,
  109. e_FillModePoint = 0x2 << e_FillModeShift,
  110. };
  111. // Notes:
  112. // Don't change the xxxShift values blindly as they affect the rendering output
  113. // that is two primitives have to be rendered after 3d primitives, alpha blended
  114. // geometry have to be rendered after opaque ones, etc.
  115. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  116. // Remarks:
  117. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  118. // Check RenderAuxGeom.h in ../RenderDll/Common
  119. // See also:
  120. // EAuxGeomPublicRenderflagBitMasks
  121. enum EAuxGeomPublicRenderflags_CullMode
  122. {
  123. e_CullModeNone = 0x0 << e_CullModeShift,
  124. e_CullModeFront = 0x1 << e_CullModeShift,
  125. e_CullModeBack = 0x2 << e_CullModeShift,
  126. };
  127. // Notes:
  128. // Don't change the xxxShift values blindly as they affect the rendering output
  129. // that is two primitives have to be rendered after 3d primitives, alpha blended
  130. // geometry have to be rendered after opaque ones, etc.
  131. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  132. // Remarks:
  133. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  134. // Check RenderAuxGeom.h in ../RenderDll/Common
  135. // See also:
  136. // EAuxGeomPublicRenderflagBitMasks
  137. enum EAuxGeomPublicRenderflags_DepthWrite
  138. {
  139. e_DepthWriteOn = 0x0 << e_DepthWriteShift,
  140. e_DepthWriteOff = 0x1 << e_DepthWriteShift,
  141. };
  142. // Notes:
  143. // Don't change the xxxShift values blindly as they affect the rendering output
  144. // that is two primitives have to be rendered after 3d primitives, alpha blended
  145. // geometry have to be rendered after opaque ones, etc.
  146. // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks!
  147. // Remarks:
  148. // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.)
  149. // Check RenderAuxGeom.h in ../RenderDll/Common
  150. // See also:
  151. // EAuxGeomPublicRenderflagBitMasks
  152. enum EAuxGeomPublicRenderflags_DepthTest
  153. {
  154. e_DepthTestOn = 0x0 << e_DepthTestShift,
  155. e_DepthTestOff = 0x1 << e_DepthTestShift,
  156. };
  157. };
  158. namespace AZ::AtomBridge
  159. {
  160. ////////////////////////////////////////////////////////////////////////
  161. SingleColorDynamicSizeLineHelper::SingleColorDynamicSizeLineHelper(
  162. int estimatedNumLineSegments
  163. )
  164. {
  165. m_points.reserve(AZStd::abs(estimatedNumLineSegments) * 2);
  166. }
  167. void SingleColorDynamicSizeLineHelper::AddLineSegment(
  168. const AZ::Vector3& lineStart,
  169. const AZ::Vector3& lineEnd
  170. )
  171. {
  172. m_points.push_back(lineStart);
  173. m_points.push_back(lineEnd);
  174. }
  175. void SingleColorDynamicSizeLineHelper::Draw(
  176. AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr,
  177. const RenderState& rendState
  178. ) const
  179. {
  180. if (auxGeomDrawPtr && !m_points.empty())
  181. {
  182. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  183. drawArgs.m_verts = m_points.data();
  184. drawArgs.m_vertCount = aznumeric_cast<uint32_t>(m_points.size());
  185. drawArgs.m_colors = &rendState.m_color;
  186. drawArgs.m_colorCount = 1;
  187. drawArgs.m_size = rendState.m_lineWidth;
  188. drawArgs.m_opacityType = rendState.m_opacityType;
  189. drawArgs.m_depthTest = rendState.m_depthTest;
  190. drawArgs.m_depthWrite = rendState.m_depthWrite;
  191. drawArgs.m_viewProjectionOverrideIndex = rendState.m_viewProjOverrideIndex;
  192. auxGeomDrawPtr->DrawLines( drawArgs );
  193. }
  194. }
  195. void SingleColorDynamicSizeLineHelper::Draw2d(
  196. AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr,
  197. const RenderState& rendState
  198. ) const
  199. {
  200. if (auxGeomDrawPtr && !m_points.empty())
  201. {
  202. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  203. drawArgs.m_verts = m_points.data();
  204. drawArgs.m_vertCount = aznumeric_cast<uint32_t>(m_points.size());
  205. drawArgs.m_colors = &rendState.m_color;
  206. drawArgs.m_colorCount = 1;
  207. drawArgs.m_size = rendState.m_lineWidth;
  208. drawArgs.m_opacityType = rendState.m_opacityType;
  209. drawArgs.m_depthTest = rendState.m_depthTest;
  210. drawArgs.m_depthWrite = rendState.m_depthWrite;
  211. drawArgs.m_viewProjectionOverrideIndex = auxGeomDrawPtr->GetOrAdd2DViewProjOverride();
  212. auxGeomDrawPtr->DrawLines( drawArgs );
  213. }
  214. }
  215. void SingleColorDynamicSizeLineHelper::Reset()
  216. {
  217. m_points.clear();
  218. }
  219. ////////////////////////////////////////////////////////////////////////
  220. AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr)
  221. {
  222. ResetRenderState();
  223. m_viewportId = viewportContextPtr->GetId();
  224. m_defaultInstance = false;
  225. auto setupScene = [this](RPI::ScenePtr scene)
  226. {
  227. auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
  228. AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId);
  229. InitInternal(scene.get(), viewportContextPtr);
  230. };
  231. setupScene(viewportContextPtr->GetRenderScene());
  232. m_sceneChangeHandler = AZ::RPI::ViewportContext::SceneChangedEvent::Handler(setupScene);
  233. viewportContextPtr->ConnectSceneChangedHandler(m_sceneChangeHandler);
  234. }
  235. AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress, RPI::Scene* scene)
  236. {
  237. ResetRenderState();
  238. m_viewportId = defaultInstanceAddress;
  239. m_defaultInstance = true;
  240. InitInternal(scene, nullptr);
  241. }
  242. void AtomDebugDisplayViewportInterface::UpdateAuxGeom(RPI::Scene* scene, AZ::RPI::View* view)
  243. {
  244. if (!scene)
  245. {
  246. m_auxGeomPtr = nullptr;
  247. return;
  248. }
  249. auto auxGeomFP = scene->GetFeatureProcessor<RPI::AuxGeomFeatureProcessorInterface>();
  250. if (!auxGeomFP)
  251. {
  252. m_auxGeomPtr = nullptr;
  253. return;
  254. }
  255. // default instance draws to all viewports in the default scene
  256. if (m_defaultInstance || !view)
  257. {
  258. m_auxGeomPtr = auxGeomFP->GetDrawQueue();
  259. }
  260. else
  261. {
  262. // cache the aux geom draw interface for the current view (aka camera)
  263. m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(view);
  264. }
  265. }
  266. void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr)
  267. {
  268. AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId);
  269. UpdateAuxGeom(scene, viewportContextPtr ? viewportContextPtr->GetDefaultView().get() : nullptr);
  270. AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId);
  271. if (!m_defaultInstance) // only the per viewport instances need to listen for viewport changes
  272. {
  273. AZ::RPI::ViewportContextIdNotificationBus::Handler::BusConnect(viewportContextPtr->GetId());
  274. }
  275. }
  276. void AtomDebugDisplayViewportInterface::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view)
  277. {
  278. ResetRenderState();
  279. if (!m_defaultInstance)
  280. {
  281. // handle viewport update (view change, scene change, etc
  282. auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
  283. AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId);
  284. UpdateAuxGeom(viewportContextPtr->GetRenderScene().get(), viewportContextPtr->GetDefaultView().get());
  285. }
  286. }
  287. AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface()
  288. {
  289. AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId);
  290. AZ::RPI::ViewportContextIdNotificationBus::Handler::BusDisconnect();
  291. m_viewportId = AzFramework::InvalidViewportId;
  292. m_auxGeomPtr = nullptr;
  293. }
  294. void AtomDebugDisplayViewportInterface::ResetRenderState()
  295. {
  296. m_rendState = RenderState();
  297. for (int index = 0; index < RenderState::TransformStackSize; ++index)
  298. {
  299. m_rendState.m_transformStack[index] = AZ::Matrix3x4::Identity();
  300. }
  301. }
  302. void AtomDebugDisplayViewportInterface::SetColor(const AZ::Color& color)
  303. {
  304. m_rendState.m_color = color;
  305. }
  306. void AtomDebugDisplayViewportInterface::SetAlpha(float a)
  307. {
  308. m_rendState.m_color.SetA(a);
  309. m_rendState.m_opacityType = a < 1.0f ? AZ::RPI::AuxGeomDraw::OpacityType::Translucent : AZ::RPI::AuxGeomDraw::OpacityType::Opaque;
  310. }
  311. void AtomDebugDisplayViewportInterface::DrawQuad(
  312. const AZ::Vector3& p1,
  313. const AZ::Vector3& p2,
  314. const AZ::Vector3& p3,
  315. const AZ::Vector3& p4)
  316. {
  317. if (m_auxGeomPtr)
  318. {
  319. AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) };
  320. AZ::Vector3 triangles[6];
  321. triangles[0] = wsPoints[0];
  322. triangles[1] = wsPoints[1];
  323. triangles[2] = wsPoints[2];
  324. triangles[3] = wsPoints[2];
  325. triangles[4] = wsPoints[3];
  326. triangles[5] = wsPoints[0];
  327. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  328. drawArgs.m_verts = triangles;
  329. drawArgs.m_vertCount = 6;
  330. drawArgs.m_colors = &m_rendState.m_color;
  331. drawArgs.m_colorCount = 1;
  332. drawArgs.m_opacityType = m_rendState.m_opacityType;
  333. drawArgs.m_depthTest = m_rendState.m_depthTest;
  334. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  335. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  336. m_auxGeomPtr->DrawTriangles(drawArgs);
  337. }
  338. }
  339. void AtomDebugDisplayViewportInterface::DrawQuad(float width, float height, bool drawShaded)
  340. {
  341. if (!m_auxGeomPtr || width <= 0.0f || height <= 0.0f)
  342. {
  343. return;
  344. }
  345. m_auxGeomPtr->DrawQuad(
  346. width,
  347. height,
  348. GetCurrentTransform(),
  349. m_rendState.m_color,
  350. drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  351. m_rendState.m_depthTest,
  352. m_rendState.m_depthWrite,
  353. m_rendState.m_faceCullMode,
  354. m_rendState.m_viewProjOverrideIndex);
  355. }
  356. void AtomDebugDisplayViewportInterface::DrawWireQuad(
  357. const AZ::Vector3& p1,
  358. const AZ::Vector3& p2,
  359. const AZ::Vector3& p3,
  360. const AZ::Vector3& p4)
  361. {
  362. if (m_auxGeomPtr)
  363. {
  364. AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) };
  365. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  366. drawArgs.m_verts = wsPoints;
  367. drawArgs.m_vertCount = 4;
  368. drawArgs.m_colors = &m_rendState.m_color;
  369. drawArgs.m_colorCount = 1;
  370. drawArgs.m_opacityType = m_rendState.m_opacityType;
  371. drawArgs.m_depthTest = m_rendState.m_depthTest;
  372. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  373. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  374. m_auxGeomPtr->DrawPolylines(drawArgs, AZ::RPI::AuxGeomDraw::PolylineEnd::Closed);
  375. }
  376. }
  377. void AtomDebugDisplayViewportInterface::DrawWireQuad(float width, float height)
  378. {
  379. if (!m_auxGeomPtr || width <= 0.0f || height <= 0.0f)
  380. {
  381. return;
  382. }
  383. m_auxGeomPtr->DrawQuad(
  384. width,
  385. height,
  386. GetCurrentTransform(),
  387. m_rendState.m_color,
  388. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  389. m_rendState.m_depthTest,
  390. m_rendState.m_depthWrite,
  391. m_rendState.m_faceCullMode,
  392. m_rendState.m_viewProjOverrideIndex);
  393. }
  394. void AtomDebugDisplayViewportInterface::DrawQuadGradient(
  395. const AZ::Vector3& p1,
  396. const AZ::Vector3& p2,
  397. const AZ::Vector3& p3,
  398. const AZ::Vector3& p4,
  399. const AZ::Vector4& firstColor,
  400. const AZ::Vector4& secondColor)
  401. {
  402. if (m_auxGeomPtr)
  403. {
  404. AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) };
  405. AZ::Vector3 triangles[6];
  406. AZ::Color colors[6];
  407. triangles[0] = wsPoints[0]; colors[0] = firstColor;
  408. triangles[1] = wsPoints[1]; colors[1] = firstColor;
  409. triangles[2] = wsPoints[2]; colors[2] = secondColor;
  410. triangles[3] = wsPoints[2]; colors[3] = secondColor;
  411. triangles[4] = wsPoints[3]; colors[4] = secondColor;
  412. triangles[5] = wsPoints[0]; colors[5] = firstColor;
  413. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  414. drawArgs.m_verts = triangles;
  415. drawArgs.m_vertCount = 6;
  416. drawArgs.m_colors = colors;
  417. drawArgs.m_colorCount = 6;
  418. drawArgs.m_opacityType = m_rendState.m_opacityType;
  419. drawArgs.m_depthTest = m_rendState.m_depthTest;
  420. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  421. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  422. m_auxGeomPtr->DrawTriangles(drawArgs);
  423. }
  424. }
  425. void AtomDebugDisplayViewportInterface::DrawQuad2dGradient(
  426. const Vector2& p1,
  427. const Vector2& p2,
  428. const Vector2& p3,
  429. const Vector2& p4,
  430. float z,
  431. const Color& firstColor,
  432. const Color& secondColor)
  433. {
  434. if (m_auxGeomPtr)
  435. {
  436. Vector3 points[4];
  437. points[0] = Vector3(p1.GetX(), p1.GetY(), z);
  438. points[1] = Vector3(p2.GetX(), p1.GetY(), z);
  439. points[2] = Vector3(p3.GetX(), p3.GetY(), z);
  440. points[3] = Vector3(p4.GetX(), p4.GetY(), z);
  441. Vector3 triangles[6];
  442. Color colors[6];
  443. triangles[0] = points[0]; colors[0] = firstColor;
  444. triangles[1] = points[1]; colors[1] = firstColor;
  445. triangles[2] = points[2]; colors[2] = secondColor;
  446. triangles[3] = points[2]; colors[3] = secondColor;
  447. triangles[4] = points[3]; colors[4] = secondColor;
  448. triangles[5] = points[0]; colors[5] = firstColor;
  449. RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  450. drawArgs.m_verts = triangles;
  451. drawArgs.m_vertCount = 6;
  452. drawArgs.m_colors = colors;
  453. drawArgs.m_colorCount = 6;
  454. const bool alphaBlend = firstColor.GetA() < 1.0f || secondColor.GetA() < 1.0f;
  455. drawArgs.m_opacityType = alphaBlend ? RPI::AuxGeomDraw::OpacityType::Translucent : RPI::AuxGeomDraw::OpacityType::Opaque;
  456. drawArgs.m_depthTest = m_rendState.m_depthTest;
  457. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  458. drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride();
  459. m_auxGeomPtr->DrawTriangles(drawArgs);
  460. }
  461. }
  462. void AtomDebugDisplayViewportInterface::DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3)
  463. {
  464. if (m_auxGeomPtr)
  465. {
  466. AZ::Vector3 verts[3] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3)};
  467. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  468. drawArgs.m_verts = verts;
  469. drawArgs.m_vertCount = 3;
  470. drawArgs.m_colors = &m_rendState.m_color;
  471. drawArgs.m_colorCount = 1;
  472. drawArgs.m_opacityType = m_rendState.m_opacityType;
  473. drawArgs.m_depthTest = m_rendState.m_depthTest;
  474. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  475. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  476. m_auxGeomPtr->DrawTriangles(drawArgs);
  477. }
  478. }
  479. void AtomDebugDisplayViewportInterface::DrawTriangles(const AZStd::vector<AZ::Vector3>& vertices, const AZ::Color& color)
  480. {
  481. if (m_auxGeomPtr)
  482. {
  483. AZStd::vector<AZ::Vector3> transformedVertices = ToWorldSpacePosition(vertices);
  484. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  485. drawArgs.m_verts = transformedVertices.data();
  486. drawArgs.m_vertCount = aznumeric_cast<uint32_t>(transformedVertices.size());
  487. drawArgs.m_colors = &color;
  488. drawArgs.m_colorCount = 1;
  489. drawArgs.m_opacityType = m_rendState.m_opacityType;
  490. drawArgs.m_depthTest = m_rendState.m_depthTest;
  491. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  492. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  493. m_auxGeomPtr->DrawTriangles(drawArgs);
  494. }
  495. }
  496. void AtomDebugDisplayViewportInterface::DrawTrianglesIndexed(
  497. const AZStd::vector<AZ::Vector3>& vertices,
  498. const AZStd::vector<AZ::u32>& indices,
  499. const AZ::Color& color)
  500. {
  501. if (m_auxGeomPtr)
  502. {
  503. AZStd::vector<AZ::Vector3> transformedVertices = ToWorldSpacePosition(vertices);
  504. AZ::RPI::AuxGeomDraw::AuxGeomDynamicIndexedDrawArguments drawArgs;
  505. drawArgs.m_verts = transformedVertices.data();
  506. drawArgs.m_vertCount = aznumeric_cast<uint32_t>(transformedVertices.size());
  507. drawArgs.m_indices = indices.data();
  508. drawArgs.m_indexCount = aznumeric_cast<uint32_t>(indices.size());
  509. drawArgs.m_colors = &color;
  510. drawArgs.m_colorCount = 1;
  511. drawArgs.m_opacityType = m_rendState.m_opacityType;
  512. drawArgs.m_depthTest = m_rendState.m_depthTest;
  513. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  514. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  515. m_auxGeomPtr->DrawTriangles(drawArgs);
  516. }
  517. }
  518. void AtomDebugDisplayViewportInterface::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max)
  519. {
  520. if (m_auxGeomPtr)
  521. {
  522. m_auxGeomPtr->DrawAabb(
  523. AZ::Aabb::CreateFromMinMax(min, max),
  524. GetCurrentTransform(),
  525. m_rendState.m_color,
  526. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  527. m_rendState.m_depthTest,
  528. m_rendState.m_depthWrite,
  529. m_rendState.m_faceCullMode,
  530. m_rendState.m_viewProjOverrideIndex
  531. );
  532. }
  533. }
  534. void AtomDebugDisplayViewportInterface::DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max)
  535. {
  536. if (m_auxGeomPtr)
  537. {
  538. m_auxGeomPtr->DrawAabb(
  539. AZ::Aabb::CreateFromMinMax(min, max),
  540. GetCurrentTransform(),
  541. m_rendState.m_color,
  542. AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  543. m_rendState.m_depthTest,
  544. m_rendState.m_depthWrite,
  545. m_rendState.m_faceCullMode,
  546. m_rendState.m_viewProjOverrideIndex);
  547. }
  548. }
  549. void AtomDebugDisplayViewportInterface::DrawWireOBB(
  550. const AZ::Vector3& center,
  551. const AZ::Vector3& axisX,
  552. const AZ::Vector3& axisY,
  553. const AZ::Vector3& axisZ,
  554. const AZ::Vector3& halfExtents)
  555. {
  556. if (m_auxGeomPtr)
  557. {
  558. AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ));
  559. AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents);
  560. m_auxGeomPtr->DrawObb(
  561. obb,
  562. AZ::Vector3::CreateZero(),
  563. m_rendState.m_color,
  564. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  565. m_rendState.m_depthTest,
  566. m_rendState.m_depthWrite,
  567. m_rendState.m_faceCullMode,
  568. m_rendState.m_viewProjOverrideIndex);
  569. }
  570. }
  571. void AtomDebugDisplayViewportInterface::DrawSolidOBB(
  572. const AZ::Vector3& center,
  573. const AZ::Vector3& axisX,
  574. const AZ::Vector3& axisY,
  575. const AZ::Vector3& axisZ,
  576. const AZ::Vector3& halfExtents)
  577. {
  578. if (m_auxGeomPtr)
  579. {
  580. AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ));
  581. AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents);
  582. m_auxGeomPtr->DrawObb(
  583. obb,
  584. AZ::Vector3::CreateZero(),
  585. m_rendState.m_color,
  586. AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  587. m_rendState.m_depthTest,
  588. m_rendState.m_depthWrite,
  589. m_rendState.m_faceCullMode,
  590. m_rendState.m_viewProjOverrideIndex);
  591. }
  592. }
  593. void AtomDebugDisplayViewportInterface::DrawPoint(const AZ::Vector3& p, int nSize)
  594. {
  595. if (m_auxGeomPtr)
  596. {
  597. AZ::Vector3 wsPoint = ToWorldSpacePosition(p);
  598. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  599. drawArgs.m_verts = &wsPoint;
  600. drawArgs.m_vertCount = 1;
  601. drawArgs.m_colors = &m_rendState.m_color;
  602. drawArgs.m_colorCount = 1;
  603. drawArgs.m_size = aznumeric_cast<uint8_t>(nSize);
  604. drawArgs.m_opacityType = m_rendState.m_opacityType;
  605. drawArgs.m_depthTest = m_rendState.m_depthTest;
  606. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  607. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  608. m_auxGeomPtr->DrawPoints(drawArgs);
  609. }
  610. }
  611. void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2)
  612. {
  613. if (m_auxGeomPtr)
  614. {
  615. AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)};
  616. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  617. drawArgs.m_verts = verts;
  618. drawArgs.m_vertCount = 2;
  619. drawArgs.m_colors = &m_rendState.m_color;
  620. drawArgs.m_colorCount = 1;
  621. drawArgs.m_size = m_rendState.m_lineWidth;
  622. drawArgs.m_opacityType = m_rendState.m_opacityType;
  623. drawArgs.m_depthTest = m_rendState.m_depthTest;
  624. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  625. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  626. m_auxGeomPtr->DrawLines(drawArgs);
  627. }
  628. }
  629. void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2)
  630. {
  631. if (m_auxGeomPtr)
  632. {
  633. AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)};
  634. AZ::Color colors[2] = {col1, col2};
  635. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  636. drawArgs.m_verts = verts;
  637. drawArgs.m_vertCount = 2;
  638. drawArgs.m_colors = colors;
  639. drawArgs.m_colorCount = 2;
  640. drawArgs.m_size = m_rendState.m_lineWidth;
  641. drawArgs.m_opacityType = m_rendState.m_opacityType;
  642. drawArgs.m_depthTest = m_rendState.m_depthTest;
  643. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  644. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  645. m_auxGeomPtr->DrawLines(drawArgs);
  646. }
  647. }
  648. void AtomDebugDisplayViewportInterface::DrawLines(const AZStd::vector<AZ::Vector3>& lines, const AZ::Color& color)
  649. {
  650. if (m_auxGeomPtr)
  651. {
  652. AZStd::vector<AZ::Vector3> transformedLines = ToWorldSpacePosition(lines);
  653. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  654. drawArgs.m_verts = transformedLines.data();
  655. drawArgs.m_vertCount = aznumeric_cast<uint32_t>(transformedLines.size());
  656. drawArgs.m_colors = &color;
  657. drawArgs.m_colorCount = 1;
  658. drawArgs.m_size = m_rendState.m_lineWidth;
  659. drawArgs.m_opacityType = m_rendState.m_opacityType;
  660. drawArgs.m_depthTest = m_rendState.m_depthTest;
  661. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  662. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  663. m_auxGeomPtr->DrawLines(drawArgs);
  664. }
  665. }
  666. void AtomDebugDisplayViewportInterface::DrawPolyLine(AZStd::span<const AZ::Vector3> points, bool cycled)
  667. {
  668. if (m_auxGeomPtr)
  669. {
  670. AZStd::vector<AZ::Vector3> wsPoints;
  671. wsPoints.resize_no_construct(points.size());
  672. AZStd::transform(points.begin(), points.end(), wsPoints.begin(), [&](auto& pnt) {
  673. return ToWorldSpacePosition(pnt);
  674. });
  675. AZ::RPI::AuxGeomDraw::PolylineEnd polylineEnd = cycled ? AZ::RPI::AuxGeomDraw::PolylineEnd::Closed : AZ::RPI::AuxGeomDraw::PolylineEnd::Open;
  676. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  677. drawArgs.m_verts = wsPoints.data();
  678. drawArgs.m_vertCount = aznumeric_cast <uint32_t>(wsPoints.size());
  679. drawArgs.m_colors = &m_rendState.m_color;
  680. drawArgs.m_colorCount = 1;
  681. drawArgs.m_size = m_rendState.m_lineWidth;
  682. drawArgs.m_opacityType = m_rendState.m_opacityType;
  683. drawArgs.m_depthTest = m_rendState.m_depthTest;
  684. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  685. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  686. m_auxGeomPtr->DrawPolylines(drawArgs, polylineEnd);
  687. }
  688. }
  689. void AtomDebugDisplayViewportInterface::DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled)
  690. {
  691. DrawPolyLine(AZStd::span<const AZ::Vector3>(pnts, numPoints), cycled);
  692. }
  693. void AtomDebugDisplayViewportInterface::DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z)
  694. {
  695. if (m_auxGeomPtr)
  696. {
  697. AZ::Vector3 points[4];
  698. points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z);
  699. points[1] = AZ::Vector3(p2.GetX(), p1.GetY(), z);
  700. points[2] = AZ::Vector3(p2.GetX(), p2.GetY(), z);
  701. points[3] = AZ::Vector3(p1.GetX(), p2.GetY(), z);
  702. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  703. drawArgs.m_verts = points;
  704. drawArgs.m_vertCount = 4;
  705. drawArgs.m_colors = &m_rendState.m_color;
  706. drawArgs.m_colorCount = 1;
  707. drawArgs.m_size = m_rendState.m_lineWidth;
  708. drawArgs.m_opacityType = m_rendState.m_opacityType;
  709. drawArgs.m_depthTest = m_rendState.m_depthTest;
  710. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  711. drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride();
  712. m_auxGeomPtr->DrawPolylines(drawArgs, AZ::RPI::AuxGeomDraw::PolylineEnd::Closed);
  713. }
  714. }
  715. void AtomDebugDisplayViewportInterface::DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z)
  716. {
  717. if (m_auxGeomPtr)
  718. {
  719. AZ::Vector3 points[2];
  720. points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z);
  721. points[1] = AZ::Vector3(p2.GetX(), p2.GetY(), z);
  722. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  723. drawArgs.m_verts = points;
  724. drawArgs.m_vertCount = 2;
  725. drawArgs.m_colors = &m_rendState.m_color;
  726. drawArgs.m_colorCount = 1;
  727. drawArgs.m_size = m_rendState.m_lineWidth;
  728. drawArgs.m_opacityType = m_rendState.m_opacityType;
  729. drawArgs.m_depthTest = m_rendState.m_depthTest;
  730. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  731. drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride();
  732. m_auxGeomPtr->DrawLines(drawArgs);
  733. }
  734. }
  735. void AtomDebugDisplayViewportInterface::DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor)
  736. {
  737. if (m_auxGeomPtr)
  738. {
  739. AZ::Vector3 points[2];
  740. points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z);
  741. points[1] = AZ::Vector3(p2.GetX(), p2.GetY(), z);
  742. AZ::Color colors[2] = {firstColor, secondColor};
  743. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  744. drawArgs.m_verts = points;
  745. drawArgs.m_vertCount = 2;
  746. drawArgs.m_colors = colors;
  747. drawArgs.m_colorCount = 2;
  748. drawArgs.m_size = m_rendState.m_lineWidth;
  749. drawArgs.m_opacityType = m_rendState.m_opacityType;
  750. drawArgs.m_depthTest = m_rendState.m_depthTest;
  751. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  752. drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride();
  753. m_auxGeomPtr->DrawLines(drawArgs);
  754. }
  755. }
  756. void AtomDebugDisplayViewportInterface::DrawWireCircle2d(const AZ::Vector2& center, float radius, float z)
  757. {
  758. if (m_auxGeomPtr)
  759. {
  760. // Draw axis aligned arc
  761. constexpr float angularStepDegrees = 10.0f;
  762. constexpr float startAngleDegrees = 0.0f;
  763. constexpr float sweepAngleDegrees = 360.0f;
  764. const float stepAngle = DegToRad(angularStepDegrees);
  765. const float startAngle = DegToRad(startAngleDegrees);
  766. const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle;
  767. SingleColorDynamicSizeLineHelper lines(1+static_cast<int>(sweepAngleDegrees/angularStepDegrees));
  768. float aspectRadius = radius / GetAspectRatio();
  769. AZ::Vector3 radiusV3 = AZ::Vector3(aspectRadius, radius, radius);
  770. AZ::Vector3 pos = AZ::Vector3(center.GetX(), center.GetY(), z);
  771. CreateAxisAlignedArc(
  772. lines,
  773. stepAngle,
  774. startAngle,
  775. stopAngle,
  776. pos,
  777. radiusV3,
  778. CircleAxis::CircleAxisZ
  779. );
  780. lines.Draw2d(m_auxGeomPtr, m_rendState);
  781. }
  782. }
  783. void AtomDebugDisplayViewportInterface::DrawArc(
  784. const AZ::Vector3& pos,
  785. float radius,
  786. float startAngleDegrees,
  787. float sweepAngleDegrees,
  788. float angularStepDegrees,
  789. int referenceAxis)
  790. {
  791. if (m_auxGeomPtr)
  792. {
  793. // Draw axis aligned arc
  794. const float stepAngle = DegToRad(angularStepDegrees);
  795. const float startAngle = DegToRad(startAngleDegrees);
  796. const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle;
  797. SingleColorDynamicSizeLineHelper lines(1+static_cast<int>(sweepAngleDegrees/angularStepDegrees));
  798. AZ::Vector3 radiusV3 = AZ::Vector3(radius);
  799. CreateAxisAlignedArc(
  800. lines,
  801. stepAngle,
  802. startAngle,
  803. stopAngle,
  804. pos,
  805. radiusV3,
  806. static_cast<CircleAxis>(referenceAxis)
  807. );
  808. lines.Draw(m_auxGeomPtr, m_rendState);
  809. }
  810. }
  811. void AtomDebugDisplayViewportInterface::DrawArc(
  812. const AZ::Vector3& pos,
  813. float radius,
  814. float startAngleDegrees,
  815. float sweepAngleDegrees,
  816. float angularStepDegrees,
  817. const AZ::Vector3& fixedAxis)
  818. {
  819. if (m_auxGeomPtr)
  820. {
  821. // Draw arbitraty axis arc
  822. const float stepAngle = DegToRad(angularStepDegrees);
  823. const float startAngle = DegToRad(startAngleDegrees);
  824. const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle;
  825. SingleColorDynamicSizeLineHelper lines(1+static_cast<int>(sweepAngleDegrees/angularStepDegrees));
  826. AZ::Vector3 radiusV3 = AZ::Vector3(radius);
  827. CreateArbitraryAxisArc(
  828. lines,
  829. stepAngle,
  830. startAngle,
  831. stopAngle,
  832. pos,
  833. radiusV3,
  834. fixedAxis
  835. );
  836. lines.Draw(m_auxGeomPtr, m_rendState);
  837. }
  838. }
  839. void AtomDebugDisplayViewportInterface::DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis)
  840. {
  841. if (m_auxGeomPtr)
  842. {
  843. // Draw circle with default radius.
  844. const float step = DegToRad(10.0f);
  845. const float maxAngle = DegToRad(360.0f) + step;
  846. SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr.
  847. AZ::Vector3 radiusV3 = AZ::Vector3(radius);
  848. CreateAxisAlignedArc(
  849. lines,
  850. step,
  851. 0.0f,
  852. maxAngle,
  853. pos,
  854. radiusV3,
  855. static_cast<CircleAxis>(nUnchangedAxis));
  856. lines.Draw(m_auxGeomPtr, m_rendState);
  857. }
  858. }
  859. void AtomDebugDisplayViewportInterface::DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis)
  860. {
  861. if (m_auxGeomPtr)
  862. {
  863. // Draw circle with single radius.
  864. const float step = DegToRad(10.0f);
  865. const float maxAngle = DegToRad(360.0f);
  866. SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr.
  867. AZ::Vector3 radiusV3 = AZ::Vector3(radius);
  868. const AZ::Vector3 worldPos = ToWorldSpacePosition(pos);
  869. const AZ::Vector3 worldView = ToWorldSpacePosition(viewPos);
  870. const AZ::Vector3 worldDir = worldView - worldPos;
  871. CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, radiusV3, static_cast<CircleAxis>(nUnchangedAxis%CircleAxisMax),
  872. [&worldPos, &worldDir](const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd, int segmentIndex)
  873. {
  874. AZ_UNUSED(lineEnd);
  875. const float dot = (lineStart - worldPos).Dot(worldDir);
  876. const bool facing = dot > 0.0f;
  877. // if so skip every other line to produce a dotted effect
  878. if (facing || segmentIndex % 2 == 0)
  879. {
  880. return true;
  881. }
  882. return false;
  883. });
  884. lines.Draw(m_auxGeomPtr, m_rendState);
  885. }
  886. }
  887. void AtomDebugDisplayViewportInterface::DrawWireCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height)
  888. {
  889. if (m_auxGeomPtr)
  890. {
  891. const AZ::Vector3 worldPos = ToWorldSpacePosition(pos);
  892. const AZ::Vector3 worldDir = ToWorldSpaceVector(dir);
  893. m_auxGeomPtr->DrawCone(
  894. worldPos,
  895. worldDir,
  896. radius,
  897. height,
  898. m_rendState.m_color,
  899. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  900. m_rendState.m_depthTest,
  901. m_rendState.m_depthWrite,
  902. m_rendState.m_faceCullMode,
  903. m_rendState.m_viewProjOverrideIndex
  904. );
  905. }
  906. }
  907. void AtomDebugDisplayViewportInterface::DrawSolidCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded)
  908. {
  909. if (m_auxGeomPtr)
  910. {
  911. const AZ::Vector3 worldPos = ToWorldSpacePosition(pos);
  912. const AZ::Vector3 worldDir = ToWorldSpaceVector(dir);
  913. m_auxGeomPtr->DrawCone(
  914. worldPos,
  915. worldDir,
  916. radius,
  917. height,
  918. m_rendState.m_color,
  919. drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  920. m_rendState.m_depthTest,
  921. m_rendState.m_depthWrite,
  922. m_rendState.m_faceCullMode,
  923. m_rendState.m_viewProjOverrideIndex
  924. );
  925. }
  926. }
  927. void AtomDebugDisplayViewportInterface::DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height)
  928. {
  929. if (m_auxGeomPtr)
  930. {
  931. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  932. const AZ::Vector3 worldCenter = ToWorldSpacePosition(center);
  933. const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis);
  934. m_auxGeomPtr->DrawCylinder(
  935. worldCenter,
  936. worldAxis,
  937. scale * radius,
  938. scale * height,
  939. m_rendState.m_color,
  940. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  941. m_rendState.m_depthTest,
  942. m_rendState.m_depthWrite,
  943. m_rendState.m_faceCullMode,
  944. m_rendState.m_viewProjOverrideIndex
  945. );
  946. }
  947. }
  948. void AtomDebugDisplayViewportInterface::DrawSolidCylinder(
  949. const AZ::Vector3& center,
  950. const AZ::Vector3& axis,
  951. float radius,
  952. float height,
  953. bool drawShaded)
  954. {
  955. if (m_auxGeomPtr)
  956. {
  957. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  958. const AZ::Vector3 worldCenter = ToWorldSpacePosition(center);
  959. const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis);
  960. m_auxGeomPtr->DrawCylinder(
  961. worldCenter,
  962. worldAxis,
  963. scale * radius,
  964. scale * height,
  965. m_rendState.m_color,
  966. drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  967. m_rendState.m_depthTest,
  968. m_rendState.m_depthWrite,
  969. m_rendState.m_faceCullMode,
  970. m_rendState.m_viewProjOverrideIndex
  971. );
  972. }
  973. }
  974. void AtomDebugDisplayViewportInterface::DrawWireCylinderNoEnds(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height)
  975. {
  976. if (m_auxGeomPtr)
  977. {
  978. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  979. const AZ::Vector3 worldCenter = ToWorldSpacePosition(center);
  980. const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis);
  981. m_auxGeomPtr->DrawCylinderNoEnds(
  982. worldCenter,
  983. worldAxis,
  984. scale * radius,
  985. scale * height,
  986. m_rendState.m_color,
  987. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  988. m_rendState.m_depthTest,
  989. m_rendState.m_depthWrite,
  990. m_rendState.m_faceCullMode,
  991. m_rendState.m_viewProjOverrideIndex
  992. );
  993. }
  994. }
  995. void AtomDebugDisplayViewportInterface::DrawSolidCylinderNoEnds(
  996. const AZ::Vector3& center,
  997. const AZ::Vector3& axis,
  998. float radius,
  999. float height,
  1000. bool drawShaded)
  1001. {
  1002. if (m_auxGeomPtr)
  1003. {
  1004. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  1005. const AZ::Vector3 worldCenter = ToWorldSpacePosition(center);
  1006. const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis);
  1007. m_auxGeomPtr->DrawCylinderNoEnds(
  1008. worldCenter,
  1009. worldAxis,
  1010. scale * radius,
  1011. scale * height,
  1012. m_rendState.m_color,
  1013. drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  1014. m_rendState.m_depthTest,
  1015. m_rendState.m_depthWrite,
  1016. m_rendState.m_faceCullMode,
  1017. m_rendState.m_viewProjOverrideIndex
  1018. );
  1019. }
  1020. }
  1021. void AtomDebugDisplayViewportInterface::DrawWireCapsule(
  1022. const AZ::Vector3& center,
  1023. const AZ::Vector3& axis,
  1024. float radius,
  1025. float heightStraightSection)
  1026. {
  1027. if (m_auxGeomPtr && radius > FLT_EPSILON && axis.GetLengthSq() > FLT_EPSILON)
  1028. {
  1029. AZ::Vector3 axisNormalized = axis.GetNormalizedEstimate();
  1030. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  1031. const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis);
  1032. // Draw cylinder part (if cylinder height is too small, ignore cylinder and just draw both hemispheres)
  1033. if (heightStraightSection > FLT_EPSILON)
  1034. {
  1035. DrawWireCylinderNoEnds(center, axis, scale * radius, scale * heightStraightSection);
  1036. }
  1037. AZ::Vector3 centerToTopCircleCenter = axisNormalized * heightStraightSection * 0.5f;
  1038. // Top hemisphere
  1039. DrawWireHemisphere(center + centerToTopCircleCenter, worldAxis, scale * radius);
  1040. // Bottom hemisphere
  1041. DrawWireHemisphere(center - centerToTopCircleCenter, -worldAxis, scale * radius);
  1042. }
  1043. }
  1044. void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, float radius)
  1045. {
  1046. if (m_auxGeomPtr)
  1047. {
  1048. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  1049. m_auxGeomPtr->DrawSphere(
  1050. ToWorldSpacePosition(pos),
  1051. scale * radius,
  1052. m_rendState.m_color,
  1053. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  1054. m_rendState.m_depthTest,
  1055. m_rendState.m_depthWrite,
  1056. m_rendState.m_faceCullMode,
  1057. m_rendState.m_viewProjOverrideIndex
  1058. );
  1059. }
  1060. }
  1061. void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius)
  1062. {
  1063. if (m_auxGeomPtr)
  1064. {
  1065. // This matches Cry behavior, the DrawWireSphere above may need modifying to use the same approach.
  1066. // Draw 3 axis aligned circles
  1067. const float step = DegToRad(10.0f);
  1068. const float maxAngle = DegToRad(360.0f);
  1069. SingleColorStaticSizeLineHelper<40*3> lines; // hard code to 40 lines * 3 circles until DegToRad is constexpr.
  1070. // Z Axis
  1071. AZ::Vector3 axisRadius(radius.GetX(), radius.GetY(), 0.0f);
  1072. CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisZ);
  1073. // X Axis
  1074. axisRadius = AZ::Vector3(0.0f, radius.GetY(), radius.GetZ());
  1075. CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisX);
  1076. // Y Axis
  1077. axisRadius = AZ::Vector3(radius.GetX(), 0.0f, radius.GetZ());
  1078. CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisY);
  1079. lines.Draw(m_auxGeomPtr, m_rendState);
  1080. }
  1081. }
  1082. void AtomDebugDisplayViewportInterface::DrawWireHemisphere(const AZ::Vector3& pos, const AZ::Vector3& axis, float radius)
  1083. {
  1084. if (m_auxGeomPtr)
  1085. {
  1086. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  1087. m_auxGeomPtr->DrawHemisphere(
  1088. ToWorldSpacePosition(pos),
  1089. axis,
  1090. scale * radius,
  1091. m_rendState.m_color,
  1092. AZ::RPI::AuxGeomDraw::DrawStyle::Line,
  1093. m_rendState.m_depthTest,
  1094. m_rendState.m_depthWrite,
  1095. m_rendState.m_faceCullMode,
  1096. m_rendState.m_viewProjOverrideIndex
  1097. );
  1098. }
  1099. }
  1100. void AtomDebugDisplayViewportInterface::DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius)
  1101. {
  1102. if (m_auxGeomPtr)
  1103. {
  1104. // Draw 3 axis aligned circles
  1105. const float stepAngle = DegToRad(11.25f);
  1106. const float startAngle = DegToRad(0.0f);
  1107. const float stopAngle = DegToRad(360.0f);
  1108. SingleColorDynamicSizeLineHelper lines(2 + static_cast<int>(360.0f / 11.25f)); // num disk segments + 1 for axis line + 1 for spare
  1109. const AZ::Vector3 radiusV3 = AZ::Vector3(radius);
  1110. CreateArbitraryAxisArc(
  1111. lines,
  1112. stepAngle,
  1113. startAngle,
  1114. stopAngle,
  1115. pos,
  1116. radiusV3,
  1117. dir
  1118. );
  1119. lines.AddLineSegment(ToWorldSpacePosition(pos), ToWorldSpacePosition(pos + dir * (radius * 0.2f))); // 0.2f comes from Code\Editor\Objects\DisplayContextShared.inl DisplayContext::DrawWireDisk
  1120. lines.Draw(m_auxGeomPtr, m_rendState);
  1121. }
  1122. }
  1123. void AtomDebugDisplayViewportInterface::DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded)
  1124. {
  1125. if (m_auxGeomPtr)
  1126. {
  1127. // get the max scaled radius in case the transform on the stack is scaled non-uniformly
  1128. const float transformedRadiusX = ToWorldSpaceVector(AZ::Vector3(radius, 0.0f, 0.0f)).GetLengthEstimate();
  1129. const float transformedRadiusY = ToWorldSpaceVector(AZ::Vector3(0.0f, radius, 0.0f)).GetLengthEstimate();
  1130. const float transformedRadiusZ = ToWorldSpaceVector(AZ::Vector3(0.0f, 0.0f, radius)).GetLengthEstimate();
  1131. const float maxTransformedRadius =
  1132. AZ::GetMax(transformedRadiusX, AZ::GetMax(transformedRadiusY, transformedRadiusZ));
  1133. AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid;
  1134. m_auxGeomPtr->DrawSphere(
  1135. ToWorldSpacePosition(pos),
  1136. maxTransformedRadius,
  1137. m_rendState.m_color,
  1138. drawStyle,
  1139. m_rendState.m_depthTest,
  1140. m_rendState.m_depthWrite,
  1141. m_rendState.m_faceCullMode,
  1142. m_rendState.m_viewProjOverrideIndex
  1143. );
  1144. }
  1145. }
  1146. void AtomDebugDisplayViewportInterface::DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, bool drawShaded)
  1147. {
  1148. if (m_auxGeomPtr)
  1149. {
  1150. const float scale = GetCurrentTransform().RetrieveScale().GetMaxElement();
  1151. const AZ::Vector3 worldPos = ToWorldSpacePosition(pos);
  1152. const AZ::Vector3 worldDir = ToWorldSpaceVector(dir);
  1153. m_auxGeomPtr->DrawDisk(
  1154. worldPos,
  1155. worldDir,
  1156. scale * radius,
  1157. m_rendState.m_color,
  1158. drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid,
  1159. m_rendState.m_depthTest,
  1160. m_rendState.m_depthWrite,
  1161. m_rendState.m_faceCullMode,
  1162. m_rendState.m_viewProjOverrideIndex
  1163. );
  1164. }
  1165. }
  1166. void AtomDebugDisplayViewportInterface::DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale, bool dualEndedArrow)
  1167. {
  1168. if (m_auxGeomPtr)
  1169. {
  1170. float f2dScale = 1.0f;
  1171. float arrowLen = 0.4f * headScale;
  1172. float arrowRadius = 0.1f * headScale;
  1173. // if (flags & DISPLAY_2D)
  1174. // {
  1175. // f2dScale = 1.2f * ToWorldSpaceVector(Vec3(1, 0, 0)).GetLength();
  1176. // }
  1177. AZ::Vector3 dir = trg - src;
  1178. dir = ToWorldSpaceVector(dir.GetNormalized());
  1179. AZ::Vector3 verts[2] = {ToWorldSpacePosition(src), ToWorldSpacePosition(trg)};
  1180. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  1181. drawArgs.m_verts = verts;
  1182. drawArgs.m_vertCount = 2;
  1183. drawArgs.m_colors = &m_rendState.m_color;
  1184. drawArgs.m_colorCount = 1;
  1185. drawArgs.m_size = m_rendState.m_lineWidth;
  1186. drawArgs.m_opacityType = m_rendState.m_opacityType;
  1187. drawArgs.m_depthTest = m_rendState.m_depthTest;
  1188. drawArgs.m_depthWrite = m_rendState.m_depthWrite;
  1189. drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex;
  1190. if (!dualEndedArrow)
  1191. {
  1192. verts[1] -= dir * arrowLen;
  1193. m_auxGeomPtr->DrawLines(drawArgs);
  1194. m_auxGeomPtr->DrawCone(
  1195. verts[1],
  1196. dir,
  1197. arrowRadius * f2dScale,
  1198. arrowLen * f2dScale,
  1199. m_rendState.m_color,
  1200. AZ::RPI::AuxGeomDraw::DrawStyle::Shaded,
  1201. m_rendState.m_depthTest,
  1202. m_rendState.m_depthWrite,
  1203. m_rendState.m_faceCullMode,
  1204. m_rendState.m_viewProjOverrideIndex
  1205. );
  1206. }
  1207. else
  1208. {
  1209. verts[0] += dir * arrowLen;
  1210. verts[1] -= dir * arrowLen;
  1211. m_auxGeomPtr->DrawLines(drawArgs);
  1212. m_auxGeomPtr->DrawCone(
  1213. verts[0],
  1214. -dir,
  1215. arrowRadius * f2dScale,
  1216. arrowLen * f2dScale,
  1217. m_rendState.m_color,
  1218. AZ::RPI::AuxGeomDraw::DrawStyle::Shaded,
  1219. m_rendState.m_depthTest,
  1220. m_rendState.m_depthWrite,
  1221. m_rendState.m_faceCullMode,
  1222. m_rendState.m_viewProjOverrideIndex
  1223. );
  1224. m_auxGeomPtr->DrawCone(
  1225. verts[1],
  1226. dir,
  1227. arrowRadius * f2dScale,
  1228. arrowLen * f2dScale,
  1229. m_rendState.m_color,
  1230. AZ::RPI::AuxGeomDraw::DrawStyle::Shaded,
  1231. m_rendState.m_depthTest,
  1232. m_rendState.m_depthWrite,
  1233. m_rendState.m_faceCullMode,
  1234. m_rendState.m_viewProjOverrideIndex
  1235. );
  1236. }
  1237. }
  1238. }
  1239. void AtomDebugDisplayViewportInterface::DrawTextLabel(
  1240. const AZ::Vector3& pos,
  1241. float size,
  1242. const char* text,
  1243. const bool center,
  1244. int srcOffsetX [[maybe_unused]],
  1245. int srcOffsetY [[maybe_unused]])
  1246. {
  1247. // abort draw if draw is invalid or font query interface is missing.
  1248. if (!text || size == 0.0f || !AZ::Interface<AzFramework::FontQueryInterface>::Get())
  1249. {
  1250. return;
  1251. }
  1252. AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface<AzFramework::FontQueryInterface>::Get()->GetDefaultFontDrawInterface();
  1253. // abort draw if font draw interface is missing
  1254. if (!fontDrawInterface)
  1255. {
  1256. return;
  1257. }
  1258. // if 2d draw need to project pos to screen first
  1259. AzFramework::TextDrawParameters params;
  1260. AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
  1261. params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works
  1262. params.m_position = pos;
  1263. params.m_color = m_rendState.m_color;
  1264. params.m_scale = AZ::Vector2(size);
  1265. params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment
  1266. params.m_monospace = false; //! disable character proportional spacing
  1267. params.m_depthTest = false; //! Test character against the depth buffer
  1268. params.m_virtual800x600ScreenSize = false; //! Text placement and size are scaled in viewport pixel coordinates
  1269. params.m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger
  1270. params.m_multiline = true; //! text respects ascii newline characters
  1271. fontDrawInterface->DrawScreenAlignedText3d(params, text);
  1272. }
  1273. void AtomDebugDisplayViewportInterface::Draw2dTextLabel(
  1274. float x,
  1275. float y,
  1276. float size,
  1277. const char* text,
  1278. bool center)
  1279. {
  1280. // abort draw if draw is invalid or font query interface is missing.
  1281. if (!text || size == 0.0f || !AZ::Interface<AzFramework::FontQueryInterface>::Get())
  1282. {
  1283. return;
  1284. }
  1285. AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface<AzFramework::FontQueryInterface>::Get()->GetDefaultFontDrawInterface();
  1286. // abort draw if font draw interface is missing
  1287. if (!fontDrawInterface)
  1288. {
  1289. return;
  1290. }
  1291. // if 2d draw need to project pos to screen first
  1292. AzFramework::TextDrawParameters params;
  1293. AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
  1294. const auto dpiScaleFactor = viewportContext->GetDpiScalingFactor();
  1295. params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works
  1296. params.m_position = AZ::Vector3(x * dpiScaleFactor, y * dpiScaleFactor, 1.0f);
  1297. params.m_color = m_rendState.m_color;
  1298. params.m_scale = AZ::Vector2(size);
  1299. params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment
  1300. params.m_monospace = false; //! disable character proportional spacing
  1301. params.m_depthTest = false; //! Test character against the depth buffer
  1302. params.m_virtual800x600ScreenSize = false; //! Text placement and size are scaled in viewport pixel coordinates
  1303. params.m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger
  1304. params.m_multiline = true; //! text respects ascii newline characters
  1305. fontDrawInterface->DrawScreenAlignedText2d(params, text);
  1306. }
  1307. void AtomDebugDisplayViewportInterface::DrawTextOn2DBox(
  1308. const AZ::Vector3& pos [[maybe_unused]],
  1309. const char* text [[maybe_unused]],
  1310. float textScale [[maybe_unused]],
  1311. const AZ::Vector4& TextColor [[maybe_unused]],
  1312. const AZ::Vector4& TextBackColor [[maybe_unused]])
  1313. {
  1314. AZ_Assert(false, "Unexpected use of legacy api, please file a feature request with the rendering team to get this implemented!");
  1315. }
  1316. void AtomDebugDisplayViewportInterface::SetLineWidth(float width)
  1317. {
  1318. AZ_Assert(width >= 0.0f && width <= 255.0f, "Width (%f) exceeds allowable range [0 - 255]", width);
  1319. m_rendState.m_lineWidth = static_cast<AZ::u8>(width);
  1320. }
  1321. bool AtomDebugDisplayViewportInterface::IsVisible(const AZ::Aabb& bounds)
  1322. {
  1323. AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
  1324. const AZ::Matrix4x4& worldToClip = viewportContext->GetDefaultView()->GetWorldToClipMatrix();
  1325. AZ::Frustum frustum = AZ::Frustum::CreateFromMatrixColumnMajor(worldToClip, Frustum::ReverseDepth::True);
  1326. return frustum.IntersectAabb(bounds) != AZ::IntersectResult::Exterior;
  1327. }
  1328. // int AtomDebugDisplayViewportInterface::SetFillMode(int nFillMode) override;
  1329. float AtomDebugDisplayViewportInterface::GetLineWidth()
  1330. {
  1331. return m_rendState.m_lineWidth;
  1332. }
  1333. float AtomDebugDisplayViewportInterface::GetAspectRatio()
  1334. {
  1335. AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
  1336. auto windowSize = viewportContext->GetViewportSize();
  1337. return aznumeric_cast<float>(windowSize.m_width)/aznumeric_cast<float>(windowSize.m_height);
  1338. }
  1339. void AtomDebugDisplayViewportInterface::DepthTestOff()
  1340. {
  1341. m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::Off;
  1342. }
  1343. void AtomDebugDisplayViewportInterface::DepthTestOn()
  1344. {
  1345. m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::On;
  1346. }
  1347. void AtomDebugDisplayViewportInterface::DepthWriteOff()
  1348. {
  1349. m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::Off;
  1350. }
  1351. void AtomDebugDisplayViewportInterface::DepthWriteOn()
  1352. {
  1353. m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On;
  1354. }
  1355. void AtomDebugDisplayViewportInterface::CullOff()
  1356. {
  1357. m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::None;
  1358. }
  1359. void AtomDebugDisplayViewportInterface::CullOn()
  1360. {
  1361. m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back;
  1362. }
  1363. bool AtomDebugDisplayViewportInterface::SetDrawInFrontMode(bool on)
  1364. {
  1365. AZ_UNUSED(on);
  1366. return false;
  1367. }
  1368. AZ::u32 AtomDebugDisplayViewportInterface::GetState()
  1369. {
  1370. return ConvertRenderStateToCry();
  1371. }
  1372. AZ::u32 AtomDebugDisplayViewportInterface::SetState(AZ::u32 state)
  1373. {
  1374. uint32_t currentState = ConvertRenderStateToCry();
  1375. uint32_t changedState = (state & e_PublicParamsMask) ^ currentState;
  1376. if (changedState & e_Mode2D3DMask)
  1377. {
  1378. // this is the only way to turn on 2d Mode under Atom
  1379. if (state & e_Mode2D)
  1380. {
  1381. AZ_Assert((currentState & e_DrawInFrontOn) == 0 && (changedState & e_DrawInFrontOn) == 0, "Atom doesnt support Draw In Front and 2d at the same time");
  1382. m_rendState.m_viewProjOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride();
  1383. m_rendState.m_2dMode = true;
  1384. }
  1385. else // switch back to mode 3d
  1386. {
  1387. m_rendState.m_viewProjOverrideIndex = -1;
  1388. m_rendState.m_2dMode = false;
  1389. }
  1390. }
  1391. if (changedState & e_AlphaBlendingMask)
  1392. {
  1393. switch (state&e_AlphaBlendingMask)
  1394. {
  1395. case e_AlphaNone:
  1396. m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque;
  1397. break;
  1398. case e_AlphaAdditive:
  1399. [[fallthrough]]; // Additive not currently supported in Atom AuxGeom implementation
  1400. case e_AlphaBlended:
  1401. m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent;
  1402. break;
  1403. }
  1404. }
  1405. if (changedState & e_DrawInFrontMask)
  1406. {
  1407. AZ_Assert( // either state is turning DrawInFront off or Mode 2D has to be off
  1408. (state & e_DrawInFrontOn) == 0 ||
  1409. ((currentState & e_Mode2D) == 0 && (changedState & e_Mode2D) == 0),
  1410. "Atom doesnt support Draw In Front and 2d at the same time");
  1411. SetDrawInFrontMode(changedState & e_DrawInFrontOn);
  1412. }
  1413. if (changedState & e_CullModeMask)
  1414. {
  1415. switch (state & e_CullModeMask)
  1416. {
  1417. case e_CullModeNone:
  1418. CullOff();
  1419. break;
  1420. case e_CullModeFront:
  1421. // Currently no other way to set front face culling in DebugDisplayRequestBus
  1422. m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Front;
  1423. break;
  1424. case e_CullModeBack:
  1425. CullOn();
  1426. break;
  1427. }
  1428. }
  1429. if (changedState & e_DepthWriteMask)
  1430. {
  1431. if (state & e_DepthWriteOff)
  1432. {
  1433. DepthWriteOff();
  1434. }
  1435. else
  1436. {
  1437. DepthWriteOn();
  1438. }
  1439. }
  1440. if (changedState & e_DepthTestMask)
  1441. {
  1442. if (state & e_DepthTestOff)
  1443. {
  1444. DepthTestOff();
  1445. }
  1446. else
  1447. {
  1448. DepthTestOn();
  1449. }
  1450. }
  1451. return currentState;
  1452. }
  1453. void AtomDebugDisplayViewportInterface::PushMatrix(const AZ::Transform& tm)
  1454. {
  1455. AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size");
  1456. if (m_rendState.m_currentTransform < RenderState::TransformStackSize)
  1457. {
  1458. m_rendState.m_currentTransform++;
  1459. m_rendState.m_transformStack[m_rendState.m_currentTransform] = m_rendState.m_transformStack[m_rendState.m_currentTransform - 1] * AZ::Matrix3x4::CreateFromTransform(tm);
  1460. }
  1461. }
  1462. void AtomDebugDisplayViewportInterface::PopMatrix()
  1463. {
  1464. AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack");
  1465. if (m_rendState.m_currentTransform > 0)
  1466. {
  1467. m_rendState.m_currentTransform--;
  1468. }
  1469. }
  1470. void AtomDebugDisplayViewportInterface::PushPremultipliedMatrix(const AZ::Matrix3x4& matrix)
  1471. {
  1472. AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size");
  1473. if (m_rendState.m_currentTransform < RenderState::TransformStackSize)
  1474. {
  1475. m_rendState.m_currentTransform++;
  1476. m_rendState.m_transformStack[m_rendState.m_currentTransform] = matrix;
  1477. }
  1478. }
  1479. AZ::Matrix3x4 AtomDebugDisplayViewportInterface::PopPremultipliedMatrix()
  1480. {
  1481. AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack");
  1482. if (m_rendState.m_currentTransform > 0)
  1483. {
  1484. m_rendState.m_currentTransform--;
  1485. }
  1486. return m_rendState.m_transformStack[m_rendState.m_currentTransform + 1];
  1487. }
  1488. const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const
  1489. {
  1490. return m_rendState.m_transformStack[m_rendState.m_currentTransform];
  1491. }
  1492. AZStd::vector<AZ::Vector3> AtomDebugDisplayViewportInterface::ToWorldSpacePosition(const AZStd::vector<AZ::Vector3>& positions) const
  1493. {
  1494. AZStd::vector<AZ::Vector3> transformedPositions;
  1495. transformedPositions.resize_no_construct(positions.size());
  1496. AZStd::transform(positions.begin(), positions.end(), transformedPositions.begin(), [this](const AZ::Vector3& position) {
  1497. return ToWorldSpacePosition(position);
  1498. });
  1499. return transformedPositions;
  1500. }
  1501. AZStd::vector<AZ::Vector3> AtomDebugDisplayViewportInterface::ToWorldSpaceVector(const AZStd::vector<AZ::Vector3>& vectors) const
  1502. {
  1503. AZStd::vector<AZ::Vector3> transformedVectors;
  1504. transformedVectors.resize_no_construct(vectors.size());
  1505. AZStd::transform(vectors.begin(), vectors.end(), transformedVectors.begin(), [this](const AZ::Vector3& vector) {
  1506. return ToWorldSpaceVector(vector);
  1507. });
  1508. return transformedVectors;
  1509. }
  1510. AZ::RPI::ViewportContextPtr AtomDebugDisplayViewportInterface::GetViewportContext() const
  1511. {
  1512. auto viewContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
  1513. if (m_defaultInstance)
  1514. {
  1515. return viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName());
  1516. }
  1517. else
  1518. {
  1519. return viewContextManager->GetViewportContextById(m_viewportId);
  1520. }
  1521. }
  1522. uint32_t AtomDebugDisplayViewportInterface::ConvertRenderStateToCry() const
  1523. {
  1524. uint32_t result = 0;
  1525. result |= m_rendState.m_2dMode ? e_Mode2D : e_Mode3D;
  1526. result |= m_rendState.m_opacityType == AZ::RPI::AuxGeomDraw::OpacityType::Opaque ? e_AlphaNone : e_AlphaBlended;
  1527. result |= m_rendState.m_drawInFront ? e_DrawInFrontOn : e_DrawInFrontOff;
  1528. result |= m_rendState.m_depthTest == AZ::RPI::AuxGeomDraw::DepthTest::On ? e_DepthTestOn : e_DepthTestOff;
  1529. result |= m_rendState.m_depthWrite == AZ::RPI::AuxGeomDraw::DepthWrite::On ? e_DepthWriteOn : e_DepthWriteOff;
  1530. switch (m_rendState.m_faceCullMode)
  1531. {
  1532. case AZ::RPI::AuxGeomDraw::FaceCullMode::None:
  1533. result |= e_CullModeNone;
  1534. break;
  1535. case AZ::RPI::AuxGeomDraw::FaceCullMode::Front:
  1536. result |= e_CullModeFront;
  1537. break;
  1538. case AZ::RPI::AuxGeomDraw::FaceCullMode::Back:
  1539. result |= e_CullModeBack;
  1540. break;
  1541. default:
  1542. AZ_Assert(false, "Trying to convert an unknown culling mode to cry!");
  1543. break;
  1544. }
  1545. return result;
  1546. }
  1547. }