Skip to content

Commit 00bbaae

Browse files
committed
UPBGE: Refactor debug shape and text drawing.
Two problems existed in the source managin the debug draw of texts and lines, cube etc… : - The text were draft directly when Render2DText was called. But this suppose that the OpenGL state have to be changed before the text render and have to be restored after the render. The same appeared for the 2d box render. - The debug shapes were stored in a private subclass of RAS_IRasterizer per scene, so every push of a debug lines needed to pass the scene pointer and the rasterizer needed to find the proper debug shape list. This can cost a lot when the push could share a statement. To fix these issue the first step was to create a special independant class managing only the debug shapes, this class is named RAS_DebugDraw. Its goal is to store the debug shapes but also to draw them using an interface named RAS_OpenGLDebugDraw for all the OpenGL calls. The rasterizer contains a list of all the debug drawer per scene, they are get through the function GetDebugDraw. Once this, the push of shapes is made as before but in the debug drawer instead of the rasterizer. The 2D texts and boxes are now stored into the debug drawer to do one OpenGL state switch before render them all and share the viewport settings. To do this the functions RenderText2D and RenderBox2D are moved in RAS_DebugDraw. In the same time the shadow is generalized by removing the "mode" argument and using BLF_SHADOW mode for the text draw. The flush function is a bit modified, it is renamed FlushDebugDraw and need a canvas to be passed, this canvas is used to compute the viewport and camera projection for 2D texts and boxes. This refactor optimized the text render time of 31% (previous 0.81ms, now 0.56ms).
1 parent 4f2f33b commit 00bbaae

18 files changed

+633
-523
lines changed

source/gameengine/Converter/BL_ArmatureObject.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ extern "C" {
5353
#include "KX_Globals.h"
5454
#include "KX_KetsjiEngine.h"
5555

56+
#include "RAS_DebugDraw.h"
57+
5658
#include "EXP_ListWrapper.h"
5759

5860
#include "MT_Matrix4x4.h"
@@ -572,7 +574,7 @@ bool BL_ArmatureObject::GetDrawDebug() const
572574
return m_drawDebug;
573575
}
574576

575-
void BL_ArmatureObject::DrawDebugArmature()
577+
void BL_ArmatureObject::DrawDebug(RAS_DebugDraw& debugDraw)
576578
{
577579
const MT_Vector3& scale = NodeGetWorldScaling();
578580
const MT_Matrix3x3& rot = NodeGetWorldOrientation();
@@ -581,7 +583,7 @@ void BL_ArmatureObject::DrawDebugArmature()
581583
for (bPoseChannel *pchan = (bPoseChannel *)m_pose->chanbase.first; pchan; pchan = pchan->next) {
582584
MT_Vector3 head = rot * (MT_Vector3(pchan->pose_head) * scale) + pos;
583585
MT_Vector3 tail = rot * (MT_Vector3(pchan->pose_tail) * scale) + pos;
584-
KX_RasterizerDrawDebugLine(tail, head, MT_Vector4(1.0f, 0.0f, 0.0f, 1.0f));
586+
debugDraw.DrawLine(tail, head, MT_Vector4(1.0f, 0.0f, 0.0f, 1.0f));
585587
}
586588
m_drawDebug = false;
587589
}

source/gameengine/Converter/BL_ArmatureObject.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct bConstraint;
4343
struct Object;
4444
class MT_Matrix4x4;
4545
class KX_BlenderSceneConverter;
46+
class RAS_DebugDraw;
4647

4748
class BL_ArmatureObject : public KX_GameObject
4849
{
@@ -107,7 +108,7 @@ class BL_ArmatureObject : public KX_GameObject
107108
Object *GetOrigArmatureObject();
108109
int GetVertDeformType();
109110
bool GetDrawDebug() const;
110-
void DrawDebugArmature();
111+
void DrawDebug(RAS_DebugDraw& debugDraw);
111112

112113
// for constraint python API
113114
void LoadConstraints(KX_BlenderSceneConverter *converter);

source/gameengine/Ketsji/KX_Globals.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ const std::string& KX_GetOrigPath()
8585

8686
void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector4& color)
8787
{
88-
g_engine->GetRasterizer()->DrawDebugLine(g_scene, from, to, color);
88+
g_engine->GetRasterizer()->GetDebugDraw(g_scene).DrawLine(from, to, color);
8989
}
9090

9191
void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector4& color,
9292
const MT_Vector3& normal, int nsector)
9393
{
94-
g_engine->GetRasterizer()->DrawDebugCircle(g_scene, center, radius, color, normal, nsector);
94+
g_engine->GetRasterizer()->GetDebugDraw(g_scene).DrawCircle(center, radius, color, normal, nsector);
9595
}

source/gameengine/Ketsji/KX_KetsjiEngine.cpp

Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,10 +1024,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene *scene, KX_Camera *cam, RAS_OffScreen
10241024
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
10251025
SG_SetActiveStage(SG_STAGE_RENDER);
10261026

1027+
RAS_DebugDraw& debugDraw = m_rasterizer->GetDebugDraw(scene);
10271028
// Draw debug infos like bouding box, armature ect.. if enabled.
1028-
scene->DrawDebug(m_rasterizer);
1029+
scene->DrawDebug(debugDraw);
10291030
// Draw debug camera frustum.
1030-
DrawDebugCameraFrustum(scene, viewport, area);
1031+
DrawDebugCameraFrustum(scene, debugDraw, viewport, area);
10311032

10321033
#ifdef WITH_PYTHON
10331034
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
@@ -1048,7 +1049,7 @@ RAS_OffScreen *KX_KetsjiEngine::PostRenderScene(KX_Scene *scene, RAS_OffScreen *
10481049
{
10491050
KX_SetActiveScene(scene);
10501051

1051-
m_rasterizer->FlushDebugShapes(scene);
1052+
m_rasterizer->FlushDebugDraw(scene, m_canvas);
10521053

10531054
// We need to first make sure our viewport is correct (enabling multiple viewports can mess this up), only for filters.
10541055
const int width = m_canvas->GetWidth();
@@ -1066,7 +1067,7 @@ RAS_OffScreen *KX_KetsjiEngine::PostRenderScene(KX_Scene *scene, RAS_OffScreen *
10661067
scene->RunDrawingCallbacks(KX_Scene::POST_DRAW, nullptr);
10671068

10681069
// Python draw callback can also call debug draw functions, so we have to clear debug shapes.
1069-
m_rasterizer->FlushDebugShapes(scene);
1070+
m_rasterizer->FlushDebugDraw(scene, m_canvas);
10701071
#endif
10711072

10721073
return offScreen;
@@ -1159,14 +1160,15 @@ void KX_KetsjiEngine::RenderDebugProperties()
11591160
tottime = 1e-6f;
11601161
}
11611162

1163+
static const MT_Vector4 white(1.0f, 1.0f, 1.0f, 1.0f);
1164+
1165+
// Use nullptrfor no scene.
1166+
RAS_DebugDraw& debugDraw = m_rasterizer->GetDebugDraw(nullptr);
1167+
11621168
if (m_show_framerate || m_show_profile) {
11631169
// Title for profiling("Profile")
1164-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1165-
"Profile",
1166-
xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
1167-
ycoord,
1168-
m_canvas->GetWidth() /* RdV, TODO ?? */,
1169-
m_canvas->GetHeight() /* RdV, TODO ?? */);
1170+
// Adds the constant x indent (0 for now) to the title x margin
1171+
debugDraw.RenderText2D("Profile", MT_Vector2(xcoord + const_xindent + title_xmargin, ycoord), white);
11701172

11711173
// Increase the indent by default increase
11721174
ycoord += const_ysize;
@@ -1176,44 +1178,28 @@ void KX_KetsjiEngine::RenderDebugProperties()
11761178

11771179
// Framerate display
11781180
if (m_show_framerate) {
1179-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1180-
"Frametime :",
1181-
xcoord + const_xindent,
1182-
ycoord,
1183-
m_canvas->GetWidth() /* RdV, TODO ?? */,
1184-
m_canvas->GetHeight() /* RdV, TODO ?? */);
1181+
debugDraw.RenderText2D("Frametime :",
1182+
MT_Vector2(xcoord + const_xindent,
1183+
ycoord), white);
11851184

11861185
debugtxt = (boost::format("%5.2fms (%.1ffps)") % (tottime * 1000.0f) % (1.0f / tottime)).str();
1187-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1188-
debugtxt,
1189-
xcoord + const_xindent + profile_indent,
1190-
ycoord,
1191-
m_canvas->GetWidth() /* RdV, TODO ?? */,
1192-
m_canvas->GetHeight() /* RdV, TODO ?? */);
1186+
debugDraw.RenderText2D(debugtxt, MT_Vector2(xcoord + const_xindent + profile_indent, ycoord), white);
11931187
// Increase the indent by default increase
11941188
ycoord += const_ysize;
11951189
}
11961190

11971191
// Profile display
11981192
if (m_show_profile) {
11991193
for (int j = tc_first; j < tc_numCategories; j++) {
1200-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1201-
m_profileLabels[j],
1202-
xcoord + const_xindent,
1203-
ycoord,
1204-
m_canvas->GetWidth(),
1205-
m_canvas->GetHeight());
1194+
debugDraw.RenderText2D(m_profileLabels[j], MT_Vector2(xcoord + const_xindent, ycoord), white);
12061195

12071196
double time = m_logger->GetAverage((KX_TimeCategory)j);
12081197

12091198
debugtxt = (boost::format("%5.2fms | %d%%") % (time*1000.f) % (int)(time/tottime * 100.f)).str();
1210-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1211-
debugtxt,
1212-
xcoord + const_xindent + profile_indent, ycoord,
1213-
m_canvas->GetWidth(),
1214-
m_canvas->GetHeight());
1199+
debugDraw.RenderText2D(debugtxt, MT_Vector2(xcoord + const_xindent + profile_indent, ycoord), white);
12151200

1216-
m_rasterizer->RenderBox2D(xcoord + (int)(2.2 * profile_indent), ycoord, m_canvas->GetWidth(), m_canvas->GetHeight(), time/tottime);
1201+
const MT_Vector2 boxSize(50 * (time / tottime), 10);
1202+
debugDraw.RenderBox2D(MT_Vector2(xcoord + (int)(2.2 * profile_indent), ycoord), boxSize, white);
12171203
ycoord += const_ysize;
12181204
}
12191205
}
@@ -1222,14 +1208,9 @@ void KX_KetsjiEngine::RenderDebugProperties()
12221208

12231209
/* Property display */
12241210
if (m_show_debug_properties) {
1225-
1226-
/* Title for debugging("Debug properties") */
1227-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1228-
"Debug Properties",
1229-
xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
1230-
ycoord,
1231-
m_canvas->GetWidth() /* RdV, TODO ?? */,
1232-
m_canvas->GetHeight() /* RdV, TODO ?? */);
1211+
// Title for debugging("Debug properties")
1212+
// Adds the constant x indent (0 for now) to the title x margin
1213+
debugDraw.RenderText2D("Debug Properties", MT_Vector2(xcoord + const_xindent + title_xmargin, ycoord), white);
12331214

12341215
// Increase the indent by default increase
12351216
ycoord += const_ysize;
@@ -1265,41 +1246,33 @@ void KX_KetsjiEngine::RenderDebugProperties()
12651246
first = false;
12661247
}
12671248
}
1268-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1269-
debugtxt,
1270-
xcoord + const_xindent,
1271-
ycoord,
1272-
m_canvas->GetWidth(),
1273-
m_canvas->GetHeight());
1249+
debugDraw.RenderText2D(debugtxt, MT_Vector2(xcoord + const_xindent, ycoord), white);
12741250
ycoord += const_ysize;
12751251
}
12761252
else {
12771253
CValue *propval = propobj->GetProperty(propname);
12781254
if (propval) {
12791255
std::string text = propval->GetText();
12801256
debugtxt = objname + ": '" + propname + "' = " + text;
1281-
m_rasterizer->RenderText2D(RAS_IRasterizer::RAS_TEXT_PADDED,
1282-
debugtxt,
1283-
xcoord + const_xindent,
1284-
ycoord,
1285-
m_canvas->GetWidth(),
1286-
m_canvas->GetHeight());
1257+
debugDraw.RenderText2D(debugtxt, MT_Vector2(xcoord + const_xindent, ycoord), white);
12871258
ycoord += const_ysize;
12881259
}
12891260
}
12901261
}
12911262
}
12921263
}
1264+
1265+
m_rasterizer->FlushDebugDraw(nullptr, m_canvas);
12931266
}
12941267

1295-
void KX_KetsjiEngine::DrawDebugCameraFrustum(KX_Scene *scene, const RAS_Rect& viewport, const RAS_Rect& area)
1268+
void KX_KetsjiEngine::DrawDebugCameraFrustum(KX_Scene *scene, RAS_DebugDraw& debugDraw, const RAS_Rect& viewport, const RAS_Rect& area)
12961269
{
12971270
CListValue *cameras = scene->GetCameraList();
12981271
for (CListValue::iterator<KX_Camera> it = cameras->GetBegin(), end = cameras->GetEnd(); it != end; ++it) {
12991272
KX_Camera *cam = *it;
13001273
if (cam->GetShowCameraFrustum()) {
13011274
const MT_Matrix4x4 viewmat(cam->GetWorldToCamera());
1302-
m_rasterizer->DrawDebugCameraFrustum(scene, GetCameraProjectionMatrix(scene, cam, viewport, area), viewmat);
1275+
debugDraw.DrawCameraFrustum(GetCameraProjectionMatrix(scene, cam, viewport, area), viewmat);
13031276
}
13041277
}
13051278
}

source/gameengine/Ketsji/KX_KetsjiEngine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class KX_KetsjiEngine
232232
RAS_OffScreen *PostRenderScene(KX_Scene *scene, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs);
233233
void RenderDebugProperties();
234234
/// Debug draw cameras frustum of a scene.
235-
void DrawDebugCameraFrustum(KX_Scene *scene, const RAS_Rect& viewport, const RAS_Rect& area);
235+
void DrawDebugCameraFrustum(KX_Scene *scene, RAS_DebugDraw& debugDraw, const RAS_Rect& viewport, const RAS_Rect& area);
236236

237237
public:
238238
KX_KetsjiEngine(KX_ISystem *system);

source/gameengine/Ketsji/KX_PythonInit.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,15 +1193,14 @@ static PyObject *gPyDrawLine(PyObject *, PyObject *args)
11931193

11941194
// Allow conversion from vector 3d.
11951195
if (PyVecTo(ob_color, color3)) {
1196-
KX_GetActiveEngine()->GetRasterizer()->DrawDebugLine(KX_GetActiveScene(), from, to,
1197-
MT_Vector4(color3.x(), color3.y(), color3.z(), 1.0f));
1196+
KX_RasterizerDrawDebugLine(from, to, MT_Vector4(color3.x(), color3.y(), color3.z(), 1.0f));
11981197
Py_RETURN_NONE;
11991198
}
12001199
else {
12011200
// Clear error message of the conversion from vector3d.
12021201
PyErr_Clear();
12031202
if (PyVecTo(ob_color, color4)) {
1204-
KX_GetActiveEngine()->GetRasterizer()->DrawDebugLine(KX_GetActiveScene(), from, to, color4);
1203+
KX_RasterizerDrawDebugLine(from, to, color4);
12051204
}
12061205
Py_RETURN_NONE;
12071206
}

source/gameengine/Ketsji/KX_Scene.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
14591459
}
14601460
}
14611461

1462-
void KX_Scene::DrawDebug(RAS_IRasterizer *rasty)
1462+
void KX_Scene::DrawDebug(RAS_DebugDraw& debugDraw)
14631463
{
14641464
const bool showBoundingBox = KX_GetActiveEngine()->GetShowBoundingBox();
14651465
if (showBoundingBox) {
@@ -1473,17 +1473,17 @@ void KX_Scene::DrawDebug(RAS_IRasterizer *rasty)
14731473
const SG_BBox& box = gameobj->GetSGNode()->BBox();
14741474
const MT_Vector3& center = box.GetCenter();
14751475

1476-
rasty->DrawDebugAabb(this, position, orientation, box.GetMin() * scale, box.GetMax() * scale,
1476+
debugDraw.DrawAabb(position, orientation, box.GetMin() * scale, box.GetMax() * scale,
14771477
MT_Vector4(1.0f, 0.0f, 1.0f, 1.0f));
14781478

14791479
// Render center in red, green and blue.
1480-
rasty->DrawDebugLine(this, orientation * center * scale + position,
1480+
debugDraw.DrawLine(orientation * center * scale + position,
14811481
orientation * (center + MT_Vector3(1.0f, 0.0f, 0.0f)) * scale + position,
14821482
MT_Vector4(1.0f, 0.0f, 0.0f, 1.0f));
1483-
rasty->DrawDebugLine(this, orientation * center * scale + position,
1483+
debugDraw.DrawLine(orientation * center * scale + position,
14841484
orientation * (center + MT_Vector3(0.0f, 1.0f, 0.0f)) * scale + position,
14851485
MT_Vector4(0.0f, 1.0f, 0.0f, 1.0f));
1486-
rasty->DrawDebugLine(this, orientation * center * scale + position,
1486+
debugDraw.DrawLine(orientation * center * scale + position,
14871487
orientation * (center + MT_Vector3(0.0f, 0.0f, 1.0f)) * scale + position,
14881488
MT_Vector4(0.0f, 0.0f, 1.0f, 1.0f));
14891489
}
@@ -1495,7 +1495,7 @@ void KX_Scene::DrawDebug(RAS_IRasterizer *rasty)
14951495
if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
14961496
BL_ArmatureObject *armature = (BL_ArmatureObject *)gameobj;
14971497
if (armature->GetDrawDebug() || KX_GetActiveEngine()->GetShowArmatures()) {
1498-
armature->DrawDebugArmature();
1498+
armature->DrawDebug(debugDraw);
14991499
}
15001500
}
15011501
}

source/gameengine/Ketsji/KX_Scene.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class RAS_BucketManager;
7979
class RAS_MaterialBucket;
8080
class RAS_IPolyMaterial;
8181
class RAS_IRasterizer;
82+
class RAS_DebugDraw;
8283
class RAS_OffScreen;
8384
class RAS_2DFilterManager;
8485
class KX_2DFilterManager;
@@ -483,7 +484,7 @@ class KX_Scene : public CValue, public SCA_IScene
483484
void SetWorldInfo(class KX_WorldInfo* wi);
484485
KX_WorldInfo* GetWorldInfo();
485486
void CalculateVisibleMeshes(RAS_IRasterizer* rasty, KX_Camera *cam, int layer=0);
486-
void DrawDebug(RAS_IRasterizer *rasty);
487+
void DrawDebug(RAS_DebugDraw& debugDraw);
487488
KX_Camera* GetpCamera();
488489
KX_BlenderSceneConverter *GetSceneConverter() { return m_sceneConverter; }
489490

source/gameengine/Rasterizer/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ set(SRC
6060
RAS_BoundingBox.cpp
6161
RAS_BoundingBoxManager.cpp
6262
RAS_BucketManager.cpp
63+
RAS_DebugDraw.cpp
6364
RAS_DisplayArrayBucket.cpp
6465
RAS_FramingManager.cpp
6566
RAS_ICanvas.cpp
@@ -90,6 +91,7 @@ set(SRC
9091
RAS_BoundingBoxManager.h
9192
RAS_BucketManager.h
9293
RAS_CameraData.h
94+
RAS_DebugDraw.h
9395
RAS_Deformer.h
9496
RAS_DisplayArray.h
9597
RAS_DisplayArrayBucket.h

0 commit comments

Comments
 (0)