mirror of
https://github.com/minetest/minetest.git
synced 2025-03-23 18:52:34 +01:00
Add debug mode that shows mesh buffer bounding boxes
This commit is contained in:
@ -34,7 +34,7 @@ enum E_DEBUG_SCENE_TYPE
|
|||||||
EDS_BBOX_ALL = EDS_BBOX | EDS_BBOX_BUFFERS,
|
EDS_BBOX_ALL = EDS_BBOX | EDS_BBOX_BUFFERS,
|
||||||
|
|
||||||
//! Show all debug infos
|
//! Show all debug infos
|
||||||
EDS_FULL = 0xffffffff
|
EDS_FULL = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
|
@ -387,6 +387,14 @@ public:
|
|||||||
pass currently is active they can render the correct part of their geometry. */
|
pass currently is active they can render the correct part of their geometry. */
|
||||||
virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0;
|
virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets debug data flags that will be set on every rendered scene node.
|
||||||
|
* Refer to `E_DEBUG_SCENE_TYPE`.
|
||||||
|
* @param setBits bit mask of types to enable
|
||||||
|
* @param unsetBits bit mask of types to disable
|
||||||
|
*/
|
||||||
|
virtual void setGlobalDebugData(u16 setBits, u16 unsetBits) = 0;
|
||||||
|
|
||||||
//! Creates a new scene manager.
|
//! Creates a new scene manager.
|
||||||
/** This can be used to easily draw and/or store two
|
/** This can be used to easily draw and/or store two
|
||||||
independent scenes at the same time. The mesh cache will be
|
independent scenes at the same time. The mesh cache will be
|
||||||
|
@ -403,14 +403,14 @@ public:
|
|||||||
their geometry because it is their only reason for existence,
|
their geometry because it is their only reason for existence,
|
||||||
for example the OctreeSceneNode.
|
for example the OctreeSceneNode.
|
||||||
\param state The culling state to be used. Check E_CULLING_TYPE for possible values.*/
|
\param state The culling state to be used. Check E_CULLING_TYPE for possible values.*/
|
||||||
void setAutomaticCulling(u32 state)
|
void setAutomaticCulling(u16 state)
|
||||||
{
|
{
|
||||||
AutomaticCullingState = state;
|
AutomaticCullingState = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets the automatic culling state.
|
//! Gets the automatic culling state.
|
||||||
/** \return The automatic culling state. */
|
/** \return The automatic culling state. */
|
||||||
u32 getAutomaticCulling() const
|
u16 getAutomaticCulling() const
|
||||||
{
|
{
|
||||||
return AutomaticCullingState;
|
return AutomaticCullingState;
|
||||||
}
|
}
|
||||||
@ -419,7 +419,7 @@ public:
|
|||||||
/** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE.
|
/** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE.
|
||||||
Please note that not all scene nodes support all debug data types.
|
Please note that not all scene nodes support all debug data types.
|
||||||
\param state The debug data visibility state to be used. */
|
\param state The debug data visibility state to be used. */
|
||||||
virtual void setDebugDataVisible(u32 state)
|
virtual void setDebugDataVisible(u16 state)
|
||||||
{
|
{
|
||||||
DebugDataVisible = state;
|
DebugDataVisible = state;
|
||||||
}
|
}
|
||||||
@ -427,7 +427,7 @@ public:
|
|||||||
//! Returns if debug data like bounding boxes are drawn.
|
//! Returns if debug data like bounding boxes are drawn.
|
||||||
/** \return A bitwise OR of the debug data values from
|
/** \return A bitwise OR of the debug data values from
|
||||||
@ref irr::scene::E_DEBUG_SCENE_TYPE that are currently visible. */
|
@ref irr::scene::E_DEBUG_SCENE_TYPE that are currently visible. */
|
||||||
u32 isDebugDataVisible() const
|
u16 isDebugDataVisible() const
|
||||||
{
|
{
|
||||||
return DebugDataVisible;
|
return DebugDataVisible;
|
||||||
}
|
}
|
||||||
@ -581,10 +581,10 @@ protected:
|
|||||||
s32 ID;
|
s32 ID;
|
||||||
|
|
||||||
//! Automatic culling state
|
//! Automatic culling state
|
||||||
u32 AutomaticCullingState;
|
u16 AutomaticCullingState;
|
||||||
|
|
||||||
//! Flag if debug data should be drawn, such as Bounding Boxes.
|
//! Flag if debug data should be drawn, such as Bounding Boxes.
|
||||||
u32 DebugDataVisible;
|
u16 DebugDataVisible;
|
||||||
|
|
||||||
//! Is the node visible?
|
//! Is the node visible?
|
||||||
bool IsVisible;
|
bool IsVisible;
|
||||||
|
@ -276,9 +276,6 @@ void CAnimatedMeshSceneNode::render()
|
|||||||
debug_mat.ZBuffer = video::ECFN_DISABLED;
|
debug_mat.ZBuffer = video::ECFN_DISABLED;
|
||||||
driver->setMaterial(debug_mat);
|
driver->setMaterial(debug_mat);
|
||||||
|
|
||||||
if (DebugDataVisible & scene::EDS_BBOX)
|
|
||||||
driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
|
|
||||||
|
|
||||||
// show bounding box
|
// show bounding box
|
||||||
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
|
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
|
||||||
for (u32 g = 0; g < m->getMeshBufferCount(); ++g) {
|
for (u32 g = 0; g < m->getMeshBufferCount(); ++g) {
|
||||||
@ -290,6 +287,9 @@ void CAnimatedMeshSceneNode::render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DebugDataVisible & scene::EDS_BBOX)
|
||||||
|
driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
|
||||||
|
|
||||||
// show skeleton
|
// show skeleton
|
||||||
if (DebugDataVisible & scene::EDS_SKELETON) {
|
if (DebugDataVisible & scene::EDS_SKELETON) {
|
||||||
if (Mesh->getMeshType() == EAMT_SKINNED) {
|
if (Mesh->getMeshType() == EAMT_SKINNED) {
|
||||||
|
@ -110,11 +110,9 @@ void CMeshSceneNode::render()
|
|||||||
if (DebugDataVisible && PassCount == 1) {
|
if (DebugDataVisible && PassCount == 1) {
|
||||||
video::SMaterial m;
|
video::SMaterial m;
|
||||||
m.AntiAliasing = 0;
|
m.AntiAliasing = 0;
|
||||||
|
m.ZBuffer = video::ECFN_DISABLED;
|
||||||
driver->setMaterial(m);
|
driver->setMaterial(m);
|
||||||
|
|
||||||
if (DebugDataVisible & scene::EDS_BBOX) {
|
|
||||||
driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
|
|
||||||
}
|
|
||||||
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
|
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
|
||||||
for (u32 g = 0; g < Mesh->getMeshBufferCount(); ++g) {
|
for (u32 g = 0; g < Mesh->getMeshBufferCount(); ++g) {
|
||||||
driver->draw3DBox(
|
driver->draw3DBox(
|
||||||
@ -123,6 +121,10 @@ void CMeshSceneNode::render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DebugDataVisible & scene::EDS_BBOX) {
|
||||||
|
driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
|
||||||
|
}
|
||||||
|
|
||||||
if (DebugDataVisible & scene::EDS_NORMALS) {
|
if (DebugDataVisible & scene::EDS_NORMALS) {
|
||||||
// draw normals
|
// draw normals
|
||||||
const f32 debugNormalLength = 1.f;
|
const f32 debugNormalLength = 1.f;
|
||||||
|
@ -490,13 +490,19 @@ void CSceneManager::drawAll()
|
|||||||
// let all nodes register themselves
|
// let all nodes register themselves
|
||||||
OnRegisterSceneNode();
|
OnRegisterSceneNode();
|
||||||
|
|
||||||
|
const auto &render_node = [this] (ISceneNode *node) {
|
||||||
|
u32 flags = node->isDebugDataVisible();
|
||||||
|
node->setDebugDataVisible((flags & DebugDataMask) | DebugDataBits);
|
||||||
|
node->render();
|
||||||
|
};
|
||||||
|
|
||||||
// render camera scenes
|
// render camera scenes
|
||||||
{
|
{
|
||||||
CurrentRenderPass = ESNRP_CAMERA;
|
CurrentRenderPass = ESNRP_CAMERA;
|
||||||
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
|
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
|
||||||
|
|
||||||
for (auto *node : CameraList)
|
for (auto *node : CameraList)
|
||||||
node->render();
|
render_node(node);
|
||||||
|
|
||||||
CameraList.clear();
|
CameraList.clear();
|
||||||
}
|
}
|
||||||
@ -507,7 +513,7 @@ void CSceneManager::drawAll()
|
|||||||
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
|
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
|
||||||
|
|
||||||
for (auto *node : SkyBoxList)
|
for (auto *node : SkyBoxList)
|
||||||
node->render();
|
render_node(node);
|
||||||
|
|
||||||
SkyBoxList.clear();
|
SkyBoxList.clear();
|
||||||
}
|
}
|
||||||
@ -520,7 +526,7 @@ void CSceneManager::drawAll()
|
|||||||
std::sort(SolidNodeList.begin(), SolidNodeList.end());
|
std::sort(SolidNodeList.begin(), SolidNodeList.end());
|
||||||
|
|
||||||
for (auto &it : SolidNodeList)
|
for (auto &it : SolidNodeList)
|
||||||
it.Node->render();
|
render_node(it.Node);
|
||||||
|
|
||||||
SolidNodeList.clear();
|
SolidNodeList.clear();
|
||||||
}
|
}
|
||||||
@ -533,7 +539,7 @@ void CSceneManager::drawAll()
|
|||||||
std::sort(TransparentNodeList.begin(), TransparentNodeList.end());
|
std::sort(TransparentNodeList.begin(), TransparentNodeList.end());
|
||||||
|
|
||||||
for (auto &it : TransparentNodeList)
|
for (auto &it : TransparentNodeList)
|
||||||
it.Node->render();
|
render_node(it.Node);
|
||||||
|
|
||||||
TransparentNodeList.clear();
|
TransparentNodeList.clear();
|
||||||
}
|
}
|
||||||
@ -546,7 +552,7 @@ void CSceneManager::drawAll()
|
|||||||
std::sort(TransparentEffectNodeList.begin(), TransparentEffectNodeList.end());
|
std::sort(TransparentEffectNodeList.begin(), TransparentEffectNodeList.end());
|
||||||
|
|
||||||
for (auto &it : TransparentEffectNodeList)
|
for (auto &it : TransparentEffectNodeList)
|
||||||
it.Node->render();
|
render_node(it.Node);
|
||||||
|
|
||||||
TransparentEffectNodeList.clear();
|
TransparentEffectNodeList.clear();
|
||||||
}
|
}
|
||||||
@ -557,7 +563,7 @@ void CSceneManager::drawAll()
|
|||||||
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
|
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
|
||||||
|
|
||||||
for (auto *node : GuiNodeList)
|
for (auto *node : GuiNodeList)
|
||||||
node->render();
|
render_node(node);
|
||||||
|
|
||||||
GuiNodeList.clear();
|
GuiNodeList.clear();
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,11 @@ public:
|
|||||||
//! Set current render time.
|
//! Set current render time.
|
||||||
void setCurrentRenderPass(E_SCENE_NODE_RENDER_PASS nextPass) override { CurrentRenderPass = nextPass; }
|
void setCurrentRenderPass(E_SCENE_NODE_RENDER_PASS nextPass) override { CurrentRenderPass = nextPass; }
|
||||||
|
|
||||||
|
void setGlobalDebugData(u16 setBits, u16 unsetBits) override {
|
||||||
|
DebugDataMask = ~unsetBits;
|
||||||
|
DebugDataBits = setBits;
|
||||||
|
}
|
||||||
|
|
||||||
//! returns if node is culled
|
//! returns if node is culled
|
||||||
bool isCulled(const ISceneNode *node) const override;
|
bool isCulled(const ISceneNode *node) const override;
|
||||||
|
|
||||||
@ -268,6 +273,9 @@ private:
|
|||||||
//! Mesh cache
|
//! Mesh cache
|
||||||
IMeshCache *MeshCache;
|
IMeshCache *MeshCache;
|
||||||
|
|
||||||
|
//! Global debug render state
|
||||||
|
u16 DebugDataMask = 0, DebugDataBits = 0;
|
||||||
|
|
||||||
E_SCENE_NODE_RENDER_PASS CurrentRenderPass;
|
E_SCENE_NODE_RENDER_PASS CurrentRenderPass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -427,6 +427,8 @@ public:
|
|||||||
|
|
||||||
const static float object_hit_delay = 0.2;
|
const static float object_hit_delay = 0.2;
|
||||||
|
|
||||||
|
const static u16 bbox_debug_flag = scene::EDS_BBOX_ALL;
|
||||||
|
|
||||||
/* The reason the following structs are not anonymous structs within the
|
/* The reason the following structs are not anonymous structs within the
|
||||||
* class is that they are not used by the majority of member functions and
|
* class is that they are not used by the majority of member functions and
|
||||||
* many functions that do require objects of thse types do not modify them
|
* many functions that do require objects of thse types do not modify them
|
||||||
@ -635,6 +637,8 @@ protected:
|
|||||||
private:
|
private:
|
||||||
struct Flags {
|
struct Flags {
|
||||||
bool disable_camera_update = false;
|
bool disable_camera_update = false;
|
||||||
|
/// 0 = no debug text active, see toggleDebug() for the rest
|
||||||
|
int debug_state = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void pauseAnimation();
|
void pauseAnimation();
|
||||||
@ -1663,6 +1667,7 @@ void Game::updateDebugState()
|
|||||||
hud->disableBlockBounds();
|
hud->disableBlockBounds();
|
||||||
if (!has_debug) {
|
if (!has_debug) {
|
||||||
draw_control->show_wireframe = false;
|
draw_control->show_wireframe = false;
|
||||||
|
smgr->setGlobalDebugData(0, bbox_debug_flag);
|
||||||
m_flags.disable_camera_update = false;
|
m_flags.disable_camera_update = false;
|
||||||
m_game_formspec.disableDebugView();
|
m_game_formspec.disableDebugView();
|
||||||
}
|
}
|
||||||
@ -2222,46 +2227,41 @@ void Game::toggleDebug()
|
|||||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||||
bool has_debug = client->checkPrivilege("debug");
|
bool has_debug = client->checkPrivilege("debug");
|
||||||
bool has_basic_debug = has_debug || (player->hud_flags & HUD_FLAG_BASIC_DEBUG);
|
bool has_basic_debug = has_debug || (player->hud_flags & HUD_FLAG_BASIC_DEBUG);
|
||||||
|
|
||||||
// Initial: No debug info
|
// Initial: No debug info
|
||||||
// 1x toggle: Debug text
|
// 1x toggle: Debug text
|
||||||
// 2x toggle: Debug text with profiler graph
|
// 2x toggle: Debug text with profiler graph
|
||||||
// 3x toggle: Debug text and wireframe (needs "debug" priv)
|
// 3x toggle: Debug text and wireframe (needs "debug" priv)
|
||||||
// Next toggle: Back to initial
|
// 4x toggle: Debug text and bbox (needs "debug" priv)
|
||||||
//
|
//
|
||||||
// The debug text can be in 2 modes: minimal and basic.
|
// The debug text can be in 2 modes: minimal and basic.
|
||||||
// * Minimal: Only technical client info that not gameplay-relevant
|
// * Minimal: Only technical client info that not gameplay-relevant
|
||||||
// * Basic: Info that might give gameplay advantage, e.g. pos, angle
|
// * Basic: Info that might give gameplay advantage, e.g. pos, angle
|
||||||
// Basic mode is used when player has the debug HUD flag set,
|
// Basic mode is used when player has the debug HUD flag set,
|
||||||
// otherwise the Minimal mode is used.
|
// otherwise the Minimal mode is used.
|
||||||
if (!m_game_ui->m_flags.show_minimal_debug) {
|
|
||||||
m_game_ui->m_flags.show_minimal_debug = true;
|
auto &state = m_flags.debug_state;
|
||||||
if (has_basic_debug)
|
state = (state + 1) % 5;
|
||||||
m_game_ui->m_flags.show_basic_debug = true;
|
if (state >= 3 && !has_debug)
|
||||||
m_game_ui->m_flags.show_profiler_graph = false;
|
state = 0;
|
||||||
draw_control->show_wireframe = false;
|
|
||||||
|
m_game_ui->m_flags.show_minimal_debug = state > 0;
|
||||||
|
m_game_ui->m_flags.show_basic_debug = state > 0 && has_basic_debug;
|
||||||
|
m_game_ui->m_flags.show_profiler_graph = state == 2;
|
||||||
|
draw_control->show_wireframe = state == 3;
|
||||||
|
smgr->setGlobalDebugData(state == 4 ? bbox_debug_flag : 0,
|
||||||
|
state == 4 ? 0 : bbox_debug_flag);
|
||||||
|
|
||||||
|
if (state == 1)
|
||||||
m_game_ui->showTranslatedStatusText("Debug info shown");
|
m_game_ui->showTranslatedStatusText("Debug info shown");
|
||||||
} else if (!m_game_ui->m_flags.show_profiler_graph && !draw_control->show_wireframe) {
|
else if (state == 2)
|
||||||
if (has_basic_debug)
|
|
||||||
m_game_ui->m_flags.show_basic_debug = true;
|
|
||||||
m_game_ui->m_flags.show_profiler_graph = true;
|
|
||||||
m_game_ui->showTranslatedStatusText("Profiler graph shown");
|
m_game_ui->showTranslatedStatusText("Profiler graph shown");
|
||||||
} else if (!draw_control->show_wireframe && client->checkPrivilege("debug")) {
|
else if (state == 3)
|
||||||
if (has_basic_debug)
|
|
||||||
m_game_ui->m_flags.show_basic_debug = true;
|
|
||||||
m_game_ui->m_flags.show_profiler_graph = false;
|
|
||||||
draw_control->show_wireframe = true;
|
|
||||||
m_game_ui->showTranslatedStatusText("Wireframe shown");
|
m_game_ui->showTranslatedStatusText("Wireframe shown");
|
||||||
} else {
|
else if (state == 4)
|
||||||
m_game_ui->m_flags.show_minimal_debug = false;
|
m_game_ui->showTranslatedStatusText("Bounding boxes shown");
|
||||||
m_game_ui->m_flags.show_basic_debug = false;
|
else
|
||||||
m_game_ui->m_flags.show_profiler_graph = false;
|
m_game_ui->showTranslatedStatusText("All debug info hidden");
|
||||||
draw_control->show_wireframe = false;
|
|
||||||
if (has_debug) {
|
|
||||||
m_game_ui->showTranslatedStatusText("Debug info, profiler graph, and wireframe hidden");
|
|
||||||
} else {
|
|
||||||
m_game_ui->showTranslatedStatusText("Debug info and profiler graph hidden");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user