Skip to content

Commit

Permalink
#5584: First TextRenderer implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jan 23, 2022
1 parent 73670ae commit 20a58d3
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 71 deletions.
2 changes: 1 addition & 1 deletion include/irender.h
Expand Up @@ -496,7 +496,7 @@ class IRenderableText
{
public:
// The position in world space where the text needs to be rendered
virtual const std::string& getWorldPosition() = 0;
virtual const Vector3& getWorldPosition() = 0;

// The text to be rendered
virtual const std::string& getText() = 0;
Expand Down
102 changes: 102 additions & 0 deletions libs/render/RenderableText.h
@@ -0,0 +1,102 @@
#pragma once

#include "irender.h"

namespace render
{

/**
* Text instance which can be attached to an ITextRenderer
* Automatially takes care of deregistering and registering
* on renderer change or destruction of this object.
*/
class RenderableText :
public IRenderableText
{
private:
Vector3 _worldPosition;
Vector4 _colour;
std::string _text;

ITextRenderer::Ptr _renderer;
ITextRenderer::Slot _slot;

public:
RenderableText(const Vector4& colour = { 0,0,0,1 }) :
_worldPosition(0,0,0),
_colour(colour),
_slot(ITextRenderer::InvalidSlot)
{}

// Noncopyable
RenderableText(const RenderableText& other) = delete;
RenderableText& operator=(const RenderableText& other) = delete;

virtual ~RenderableText()
{
clear();
}

void update(const ITextRenderer::Ptr& renderer)
{
bool rendererChanged = _renderer != renderer;

if (rendererChanged)
{
clear();
}

// Update our local reference
_renderer = renderer;

if (_renderer && _slot == ITextRenderer::InvalidSlot)
{
_slot = _renderer->addText(*this);
}
}

void clear()
{
removeTextFromRenderer();
_renderer.reset();
}

const Vector3& getWorldPosition() override
{
return _worldPosition;
}

void setWorldPosition(const Vector3& position)
{
_worldPosition = position;
}

const std::string& getText() override
{
return _text;
}

void setText(const std::string& text)
{
_text = text;
}

const Vector4& getColour() override
{
return _colour;
}

private:
// Removes the text from the attached renderer. Does nothing if no text has been added.
void removeTextFromRenderer()
{
if (_renderer && _slot != ITextRenderer::InvalidSlot)
{
_renderer->removeText(_slot);
}

_slot = ITextRenderer::InvalidSlot;
}
};

}
3 changes: 3 additions & 0 deletions radiantcore/rendersystem/OpenGLRenderSystem.cpp
Expand Up @@ -227,6 +227,9 @@ void OpenGLRenderSystem::render(RenderViewType renderViewType,
pair.second->clearRenderables();
}

// Render any text
_textRenderer->render();

glPopAttrib();
}

Expand Down
34 changes: 22 additions & 12 deletions radiantcore/rendersystem/backend/TextRenderer.h
@@ -1,5 +1,6 @@
#pragma once

#include "igl.h"
#include "irender.h"

namespace render
Expand All @@ -9,20 +10,12 @@ class TextRenderer final :
public ITextRenderer
{
private:
struct TextInfo
{
bool occupied;
std::reference_wrapper<IRenderableText> text;

TextInfo(IRenderableText& text_) :
text(text_),
occupied(true)
{}
};
std::map<Slot, TextInfo> _slots;
std::map<Slot, std::reference_wrapper<IRenderableText>> _slots;

Slot _freeSlotMappingHint;

IGLFont::Ptr _glFont;

public:
TextRenderer() :
_freeSlotMappingHint(0)
Expand Down Expand Up @@ -51,7 +44,24 @@ class TextRenderer final :

void render()
{
// TODO
if (!_glFont)
{
// TODO: make size and style configurable
_glFont = GlobalOpenGL().getFont(IGLFont::Style::Sans, 14);
}

for (const auto& [_, ref] : _slots)
{
auto& renderable = ref.get();
const auto& text = renderable.getText();

if (text.empty()) continue;

glColor4dv(renderable.getColour());
glRasterPos3dv(renderable.getWorldPosition());

_glFont->drawString(text);
}
}

private:
Expand Down
6 changes: 0 additions & 6 deletions radiantcore/selection/RadiantSelectionSystem.cpp
Expand Up @@ -868,20 +868,14 @@ const Matrix4& RadiantSelectionSystem::getPivot2World()

void RadiantSelectionSystem::captureShaders()
{
auto manipulatorFontStyle = registry::getValue<std::string>(RKEY_MANIPULATOR_FONTSTYLE) == "Sans" ?
IGLFont::Style::Sans : IGLFont::Style::Mono;
auto manipulatorFontSize = registry::getValue<int>(RKEY_MANIPULATOR_FONTSIZE);

TranslateManipulator::_stateWire = GlobalRenderSystem().capture("$WIRE_OVERLAY");
TranslateManipulator::_stateFill = GlobalRenderSystem().capture("$FLATSHADE_OVERLAY");
RotateManipulator::_glFont = GlobalOpenGL().getFont(manipulatorFontStyle, manipulatorFontSize);
}

void RadiantSelectionSystem::releaseShaders()
{
TranslateManipulator::_stateWire.reset();
TranslateManipulator::_stateFill.reset();
RotateManipulator::_glFont.reset();
}

const WorkZone& RadiantSelectionSystem::getWorkZone()
Expand Down
71 changes: 26 additions & 45 deletions radiantcore/selection/manipulators/RotateManipulator.cpp
Expand Up @@ -13,6 +13,7 @@ namespace
{
constexpr static auto CircleSegments = 8;
constexpr static auto CircleRadius = 64.0;
const Vector4 AngleTextColour(0.75, 0, 0, 1);
}

RotateManipulator::RotateManipulator(ManipulationPivot& pivot, std::size_t segments, float radius) :
Expand All @@ -27,7 +28,8 @@ RotateManipulator::RotateManipulator(ManipulationPivot& pivot, std::size_t segme
_circleZ(CircleSegments, CircleRadius, _local2worldZ),
_circleScreen(CircleSegments, CircleRadius * 1.15, _pivot2World._viewpointSpace),
_circleSphere(CircleSegments, CircleRadius, _pivot2World._viewpointSpace),
_pivotPoint(_localPivotPoint, _pivot2World._worldSpace)
_pivotPoint(_localPivotPoint, _pivot2World._worldSpace),
_angleText(AngleTextColour)
{}

void RotateManipulator::updateColours()
Expand Down Expand Up @@ -104,48 +106,27 @@ void RotateManipulator::onPreRender(const RenderSystemPtr& renderSystem, const V
_pivotPointShader = renderSystem->capture("$BIGPOINT");
}

if (!_textRenderer)
{
/*auto manipulatorFontStyle = registry::getValue<std::string>(RKEY_MANIPULATOR_FONTSTYLE) == "Sans" ?
IGLFont::Style::Sans : IGLFont::Style::Mono;
auto manipulatorFontSize = registry::getValue<int>(RKEY_MANIPULATOR_FONTSIZE);*/
_textRenderer = renderSystem->captureTextRenderer();
}

_pivot2World.update(_pivot.getMatrix4(), volume.GetModelview(), volume.GetProjection(), volume.GetViewport());

updateCircleTransforms();

updateColours();
updateAngleText();

_circleX.update(_lineShader);
_circleY.update(_lineShader);
_circleZ.update(_lineShader);
_circleScreen.update(_lineShader);
_circleSphere.update(_lineShader);
_pivotPoint.update(_pivotPointShader);
}

void RotateManipulator::render(IRenderableCollector& collector, const VolumeTest& volume)
{
#if 0
_pivot2World.update(_pivot.getMatrix4(), volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
updateCircleTransforms();

// temp hack
updateColours();

collector.addRenderable(*_stateOuter, _circleScreen, _pivot2World._viewpointSpace);
collector.addRenderable(*_stateOuter, _circleSphere, _pivot2World._viewpointSpace);

if(_circleX_visible)
{
collector.addRenderable(*_stateOuter, _circleX, _local2worldX);
}
if(_circleY_visible)
{
collector.addRenderable(*_stateOuter, _circleY, _local2worldY);
}
if(_circleZ_visible)
{
collector.addRenderable(*_stateOuter, _circleZ, _local2worldZ);
}

collector.addRenderable(*_pivotPointShader, _pivotPoint, _pivot2World._worldSpace);

collector.addRenderable(*_pivotPointShader, *this, Matrix4::getIdentity());
#endif
_angleText.update(_textRenderer);
}

void RotateManipulator::clearRenderables()
Expand All @@ -156,8 +137,10 @@ void RotateManipulator::clearRenderables()
_circleScreen.clear();
_circleSphere.clear();
_pivotPoint.clear();
_angleText.clear();
_lineShader.reset();
_pivotPointShader.reset();
_textRenderer.reset();
}

std::string RotateManipulator::getRotationAxisName() const
Expand All @@ -169,20 +152,21 @@ std::string RotateManipulator::getRotationAxisName() const
return std::string();
}

void RotateManipulator::render(const RenderInfo& info) const
void RotateManipulator::updateAngleText()
{
if (_selectableX.isSelected() || _selectableY.isSelected() ||
_selectableZ.isSelected() || _selectableScreen.isSelected())
{
glColor3d(0.75, 0, 0);

glRasterPos3dv(_pivot2World._worldSpace.translation() - Vector3(10, 10, 10));

double angle = static_cast<double>(c_RAD2DEGMULT * _rotateAxis.getCurAngle());
{
double angle = static_cast<double>(c_RAD2DEGMULT * _rotateAxis.getCurAngle());
auto rotationAxisName = getRotationAxisName();

_glFont->drawString(fmt::format("Rotate: {0:3.2f} degrees {1}", angle, rotationAxisName));
}
_angleText.setText(fmt::format("Rotate: {0:3.2f} degrees {1}", angle, rotationAxisName));
_angleText.setWorldPosition(_pivot2World._worldSpace.translation() - Vector3(10, 10, 10));
}
else
{
_angleText.setText("");
}
}

void RotateManipulator::testSelect(SelectionTest& test, const Matrix4& pivot2world)
Expand Down Expand Up @@ -318,7 +302,4 @@ void RotateManipulator::rotate(const Quaternion& rotation)
SceneChangeNotify();
}

// Static members
IGLFont::Ptr RotateManipulator::_glFont;

}
13 changes: 6 additions & 7 deletions radiantcore/selection/manipulators/RotateManipulator.h
Expand Up @@ -10,6 +10,7 @@
#include "selection/ManipulationPivot.h"
#include "render.h"
#include "Renderables.h"
#include "render/RenderableText.h"

namespace selection
{
Expand All @@ -22,8 +23,7 @@ namespace selection
*/
class RotateManipulator :
public ManipulatorBase,
public Rotatable,
public OpenGLRenderable
public Rotatable
{
private:
ManipulationPivot& _pivot;
Expand All @@ -41,6 +41,8 @@ class RotateManipulator :
RenderableCircle<RemapXYZ> _circleScreen;
RenderableCircle<RemapXYZ> _circleSphere;
RenderablePoint _pivotPoint;
render::RenderableText _angleText;

BasicSelectable _selectableX;
BasicSelectable _selectableY;
BasicSelectable _selectableZ;
Expand All @@ -57,11 +59,9 @@ class RotateManipulator :

ShaderPtr _lineShader;
ShaderPtr _pivotPointShader;
ITextRenderer::Ptr _textRenderer;

public:
static IGLFont::Ptr _glFont;

// Constructor
RotateManipulator(ManipulationPivot& pivot, std::size_t segments, float radius);

Type getType() const override
Expand All @@ -70,8 +70,6 @@ class RotateManipulator :
}

void onPreRender(const RenderSystemPtr& renderSystem, const VolumeTest& volume) override;
void render(IRenderableCollector& collector, const VolumeTest& volume) override;
void render(const RenderInfo& info) const override;
void clearRenderables() override;

void testSelect(SelectionTest& view, const Matrix4& pivot2world) override;
Expand All @@ -86,6 +84,7 @@ class RotateManipulator :
private:
void updateColours();
void updateCircleTransforms();
void updateAngleText();

std::string getRotationAxisName() const;
};
Expand Down
1 change: 1 addition & 0 deletions tools/msvc/libs.vcxproj
Expand Up @@ -221,6 +221,7 @@
<ClInclude Include="..\..\libs\render\RenderablePivot.h" />
<ClInclude Include="..\..\libs\render\RenderableSpacePartition.h" />
<ClInclude Include="..\..\libs\render\RenderableSurface.h" />
<ClInclude Include="..\..\libs\render\RenderableText.h" />
<ClInclude Include="..\..\libs\render\SceneRenderWalker.h" />
<ClInclude Include="..\..\libs\render\TexCoord2f.h" />
<ClInclude Include="..\..\libs\render\TextureToolView.h" />
Expand Down

0 comments on commit 20a58d3

Please sign in to comment.