!I (1670409):
[CRYENGINE.git] / Code / CryEngine / Cry3DEngine / ParticleSystem / ParticleDebug.cpp
blob6c591926ab776a2eecfcd8df1d5254b16d2f8f02
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 // -------------------------------------------------------------------------
4 // Created: 06/02/2015 by Filipe amim
5 // Description:
6 // -------------------------------------------------------------------------
7 //
8 ////////////////////////////////////////////////////////////////////////////
10 #include "StdAfx.h"
11 #include <CryMath/FinalizingSpline.h>
12 #include "ParticleCommon.h"
13 #include "ParticleDebug.h"
14 #include "ParticleContainer.h"
15 #include "ParticleComponent.h"
16 #include "ParticleComponentRuntime.h"
17 #include "ParticleEffect.h"
18 #include "ParticleEmitter.h"
19 #include "Features/FeatureCollision.h"
21 CRY_PFX2_DBG
23 namespace pfx2
26 #if !defined(_RELEASE)
28 namespace
31 const ColorB black(0, 0, 0);
32 const ColorB white(255, 255, 255);
33 const ColorF whiteF(1.0f, 1.0f, 1.0f);
34 const ColorB lightOrange(255, 198, 128);
35 const ColorB red(192, 23, 32);
36 const ColorB darkRed(96, 0, 0);
38 const float startPos = 1.0f / 40.0f;
39 const float barSz = 1.0f / 192.0f;
40 const float barGap = 1.0f / 24.0f;
42 void DebugDrawEffect(CParticleEffect* pEffect, size_t effectBarIdx)
44 #if 0
45 // emitter bars
46 IRenderer* pRender = gEnv->pRenderer;
47 IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom();
49 const float screenWidth = pRenderAux->GetCamera().GetViewSurfaceX();
50 const float screenHeight = pRenderAux->GetCamera().GetViewSurfaceZ();
52 const Vec2 screenSz = Vec2(screenWidth, screenHeight);
53 const Vec2 pixSz = Vec2(1.0f / screenWidth, 1.0f / screenHeight);
55 size_t numEmitters = pEffect->GetEmitterCount();
56 const Vec2 emitterSz = Vec2(barSz, 0.9f / numEmitters);
57 const Vec2 emitterLoc = Vec2(effectBarIdx * barGap + startPos, startPos);
59 Vec3 pos = Vec2(effectBarIdx * barGap + startPos, startPos);
60 for (size_t i = 0; i < numEmitters; ++i)
62 AABB box;
63 box.min = pos;
64 box.max.x = box.min.x + std::max(emitterSz.x, pixSz.x);
65 box.max.y = box.min.y + std::max(emitterSz.y - pixSz.y, pixSz.y);
66 ColorB color = pEffect->GetEmitter(i).m_active ? red : darkRed;
67 pRenderAux->DrawAABB(box, true, color, eBBD_Faceted);
68 pos.y += emitterSz.y;
71 pRender->Draw2dLabel(
72 screenSz.x * (effectBarIdx * barGap + startPos),
73 screenSz.y * 0.975f, 1.0f, whiteF, false,
74 pEffect->GetName());
75 #endif
78 void DebugDrawComponentRuntime(CParticleComponentRuntime* pRuntime, size_t emitterBarIdx, size_t barIdx)
80 IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom();
81 SAuxGeomRenderFlags prevFlags = pRenderAux->GetRenderFlags();
82 SAuxGeomRenderFlags curFlags = prevFlags;
83 curFlags.SetMode2D3DFlag(e_Mode2D);
84 curFlags.SetDepthTestFlag(e_DepthTestOff);
85 curFlags.SetDepthWriteFlag(e_DepthWriteOff);
86 pRenderAux->SetRenderFlags(curFlags);
88 const float screenWidth = float(pRenderAux->GetCamera().GetViewSurfaceX());
89 const float screenHeight = float(pRenderAux->GetCamera().GetViewSurfaceZ());
91 const SUpdateContext context = SUpdateContext(pRuntime);
92 const CParticleContainer& container = context.m_container;
93 const SComponentParams& params = context.m_params;
94 const uint numInstances = pRuntime->GetNumInstances();
95 IPidStream parentIds = container.GetIPidStream(EPDT_ParentId);
96 IFStream normAges = container.GetIFStream(EPDT_NormalAge);
97 const Vec2 screenSz = Vec2(screenWidth, screenHeight);
98 const Vec2 pixSz = Vec2(1.0f / screenWidth, 1.0f / screenHeight);
99 const Vec2 partSz = Vec2(barSz, 0.9f / container.GetMaxParticles());
100 const Vec2 contLoc = Vec2(barIdx * barGap + barSz * 3.0f + startPos, startPos);
101 const float off = barSz * 0.5f;
102 Vec2 pos;
104 // instance bars
105 if (numInstances)
107 const Vec2 instSz = Vec2(barSz, 0.9f / numInstances);
108 const Vec2 instLoc = Vec2(barIdx * barGap + startPos, startPos);
109 pos = instLoc;
110 for (uint i = 0; i < numInstances; ++i)
112 AABB box;
113 box.min = pos;
114 box.max.x = box.min.x + std::max(instSz.x, pixSz.x);
115 box.max.y = box.min.y + std::max(instSz.y - pixSz.y, pixSz.y);
116 ColorF color = ColorF(0.0f, 0.5f, 1.0f);
117 pRenderAux->DrawAABB(box, true, ColorB(color), eBBD_Faceted);
118 pos.y += instSz.y;
122 // particle bars
123 pos = contLoc;
124 for (auto particleId : context.GetUpdateRange())
126 AABB box;
127 // box.min = pos;
128 box.min.x = contLoc.x;
129 box.min.y = contLoc.y + partSz.y * particleId;
130 box.max.x = box.min.x + std::max(partSz.x, pixSz.x);
131 box.max.y = box.min.y + std::max(partSz.y - pixSz.y, pixSz.y);
132 ColorB color = black;
133 const float age = normAges.Load(particleId);
134 if (IsAlive(age))
135 color = ColorB(ColorF(age, 1.0f - age, 0.0f));
136 pRenderAux->DrawAABB(box, true, color, eBBD_Faceted);
139 if (pRuntime->IsChild())
141 const CParticleContainer& parentContainer = pRuntime->GetParentContainer();
142 const Vec2 parentPartSz = Vec2(barSz, 0.9f / parentContainer.GetMaxParticles());
143 const Vec2 parentContLoc = Vec2((emitterBarIdx /*+ params.m_parentId*/) * barGap + barSz * 3.0f + startPos, startPos);
145 // parenting lines
146 for (auto particleId : context.GetUpdateRange())
148 const TParticleId parentId = parentIds.Load(particleId);
149 if (parentId == gInvalidId)
150 continue;
151 Vec2 from = contLoc + partSz * 0.5f + Vec2(-off, partSz.y * particleId);
152 Vec2 to = parentContLoc + parentPartSz * 0.5f + Vec2(off, parentPartSz.y * parentId);
153 pRenderAux->DrawLine(from, lightOrange, to, black, 1.0f);
157 IRenderAuxText::Draw2dLabel(
158 screenSz.x * (barIdx * barGap + startPos),
159 screenSz.y * 0.95f, 1.0f, whiteF, false,
160 "%s", pRuntime->GetComponent()->GetName());
162 pRenderAux->SetRenderFlags(prevFlags);
165 void DebugDrawComponentCollisions(CParticleComponentRuntime* pRuntime)
167 IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom();
168 SAuxGeomRenderFlags prevFlags = pRenderAux->GetRenderFlags();
169 SAuxGeomRenderFlags curFlags = prevFlags;
170 curFlags.SetMode2D3DFlag(e_Mode3D);
171 curFlags.SetDepthTestFlag(e_DepthTestOn);
172 curFlags.SetDepthWriteFlag(e_DepthWriteOn);
173 pRenderAux->SetRenderFlags(curFlags);
175 const auto context = SUpdateContext(pRuntime);
176 const CParticleContainer& container = pRuntime->GetContainer();
177 if (!container.HasData(EPDT_ContactPoint))
178 return;
179 const TIStream<SContactPoint> contactPoints = container.IStream(EPDT_ContactPoint);
181 for (auto particleId : context.GetUpdateRange())
183 SContactPoint contact = contactPoints.Load(particleId);
185 if (contact.m_totalCollisions == 0)
186 continue;
188 ColorB color = ColorB(0, 0, 0);
189 if (contact.m_state.ignore)
190 color = ColorB(128, 128, 128);
191 else if (contact.m_state.sliding)
192 color = ColorB(255, 128, 64);
193 else
194 color = ColorB(64, 128, 255);
196 pRenderAux->DrawSphere(contact.m_point, 0.05f, color);
197 pRenderAux->DrawLine(
198 contact.m_point, color,
199 contact.m_point + contact.m_normal*0.25f, color);
202 pRenderAux->SetRenderFlags(prevFlags);
205 #if CRY_PLATFORM_SSE2
207 void DrawLineSSE(IRenderAuxGeom* pRenderAux, __m128 x, __m128 y, ColorB color)
209 #if 0
210 pRenderAux->DrawLine(
211 Vec2(x.m128_f32[3], (1.0f - y.m128_f32[3]) * 0.9f + 0.05f), color,
212 Vec2(x.m128_f32[2], (1.0f - y.m128_f32[2]) * 0.9f + 0.05f), color, 1.0f);
213 pRenderAux->DrawLine(
214 Vec2(x.m128_f32[2], (1.0f - y.m128_f32[2]) * 0.9f + 0.05f), color,
215 Vec2(x.m128_f32[1], (1.0f - y.m128_f32[1]) * 0.9f + 0.05f), color, 1.0f);
216 pRenderAux->DrawLine(
217 Vec2(x.m128_f32[1], (1.0f - y.m128_f32[1]) * 0.9f + 0.05f), color,
218 Vec2(x.m128_f32[0], (1.0f - y.m128_f32[0]) * 0.9f + 0.05f), color, 1.0f);
219 #endif
222 #endif
224 void DebugOptSpline()
226 #if 0
227 typedef spline::OptSpline<float> TOptSplineF;
229 static bool init = false;
230 static TOptSplineF optSpline;
231 static CParticleSpline particleSpline;
232 if (!init)
234 init = true;
236 CParticleSpline::CSourceSpline source;
237 CParticleSpline::CSourceSpline::key_type key;
239 key.flags =
240 (SPLINE_KEY_TANGENT_LINEAR << SPLINE_KEY_TANGENT_IN_SHIFT) |
241 (SPLINE_KEY_TANGENT_NONE << SPLINE_KEY_TANGENT_OUT_SHIFT);
242 key.time = 0.1f;
243 key.value = 0.2f;
244 source.insert_key(key);
245 key.time = 0.25f;
246 key.value = 1.0f;
247 source.insert_key(key);
248 key.time = 0.7f;
249 key.value = 0.5f;
250 source.insert_key(key);
251 key.time = 0.95f;
252 key.value = 0.0f;
253 source.insert_key(key);
255 source.update();
256 optSpline.from_source(source);
257 particleSpline.FromSpline(source);
260 IRenderer* pRender = gEnv->pRenderer;
261 IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom();
262 SAuxGeomRenderFlags prevFlags = pRenderAux->GetRenderFlags();
263 SAuxGeomRenderFlags curFlags = prevFlags;
264 Vec2 screenSz = Vec2(float(gEnv->pRenderer->GetWidth()), float(gEnv->pRenderer->GetHeight()));
265 curFlags.SetMode2D3DFlag(e_Mode2D);
266 pRenderAux->SetRenderFlags(curFlags);
268 const int numSamples = 100;
269 const float sampleSz = 1.0f / numSamples;
270 float prevValue;
272 optSpline.interpolate(0.0f, prevValue);
273 for (float t = sampleSz; t <= 1.0f; t += sampleSz)
275 float curValue;
276 optSpline.interpolate(t, curValue);
277 pRenderAux->DrawLine(
278 Vec2(t - sampleSz, (1.0f - prevValue) * 0.9f + 0.05f), red,
279 Vec2(t, (1.0f - curValue) * 0.9f + 0.05f), red, 1.0f);
280 prevValue = curValue;
283 prevValue = particleSpline.Interpolate(0.0f);
284 for (float t = sampleSz; t <= 1.0f; t += sampleSz)
286 float curValue;
287 curValue = particleSpline.Interpolate(t);
288 pRenderAux->DrawLine(
289 Vec2(t - sampleSz, (1.0f - prevValue) * 0.9f + 0.05f), lightOrange,
290 Vec2(t, (1.0f - curValue) * 0.9f + 0.05f), lightOrange, 1.0f);
291 prevValue = curValue;
294 const ColorB blue(128, 198, 255);
295 for (float t = 0.0f; t < 1.0f; t += sampleSz * 4.0f)
297 __m128 timeSSE = _mm_set_ps(t, t + sampleSz, t + sampleSz * 2.0f, t + sampleSz * 3.0f);
298 __m128 curValueSSE = particleSpline.Interpolate(timeSSE);
299 DrawLineSSE(pRenderAux, timeSSE, curValueSSE, blue);
302 pRenderAux->SetRenderFlags(prevFlags);
303 #endif
308 void DebugParticleSystem(const TParticleEmitters& activeEmitters)
310 DebugOptSpline();
312 CVars* pCVars = static_cast<C3DEngine*>(gEnv->p3DEngine)->GetCVars();
313 const bool debugContainers = (pCVars->e_ParticlesDebug & AlphaBit('c')) != 0;
314 const bool debugCollisions = (pCVars->e_ParticlesDebug & AlphaBit('k')) != 0;
316 if (debugContainers || debugCollisions)
318 IRenderer* pRender = gEnv->pRenderer;
319 IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom();
321 size_t emitterBarIdx = 0;
322 size_t barIdx = 0;
323 for (CParticleEmitter* pEmitter : activeEmitters)
325 CParticleEffect* pEffect = pEmitter->GetCEffect();
326 for (auto pRuntime : pEmitter->GetRuntimes())
328 auto pComponentRuntime = pRuntime->GetCpuRuntime();
329 if (!pComponentRuntime)
330 continue;
331 if (!pComponentRuntime->GetComponent()->IsEnabled())
332 continue;
333 if (debugContainers)
334 DebugDrawComponentRuntime(pComponentRuntime, emitterBarIdx, barIdx++);
335 if (debugCollisions)
336 DebugDrawComponentCollisions(pComponentRuntime);
338 emitterBarIdx = barIdx;
343 #else
345 void DebugParticleSystem(const TParticleEmitters& activeEmitters) {}
347 #endif