Skip to content

Commit

Permalink
#5584: Start working on RotateManipulator class.
Browse files Browse the repository at this point in the history
Since the drawing is view-dependent, the geometry is updated every single frame in onPreRender.
  • Loading branch information
codereader committed Jan 22, 2022
1 parent afb2f5e commit 2d64d9f
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 31 deletions.
6 changes: 6 additions & 0 deletions libs/render.h
Expand Up @@ -361,6 +361,12 @@ class RenderableIndexBuffer : public OpenGLRenderable
template<typename VertexContainerT> struct RemappingTraits
{};

template<>
struct RemappingTraits<Vertex3f>
{
static Vertex3f& getVertex(Vertex3f& vertex) { return vertex; }
};

template<>
struct RemappingTraits<VertexCb>
{
Expand Down
4 changes: 2 additions & 2 deletions libs/selection/BestPoint.h
Expand Up @@ -454,12 +454,12 @@ inline std::size_t clipLine(const Matrix4& matrix, const Vector3& p0,
return homogenous_clip_line(clipped);
}

inline void LineStrip_BestPoint(const Matrix4& local2view, const VertexCb* vertices, const std::size_t size, SelectionIntersection& best)
inline void LineStrip_BestPoint(const Matrix4& local2view, const Vector3* vertices, const std::size_t size, SelectionIntersection& best)
{
Vector4 clipped[2];
for (std::size_t i = 0; (i + 1) < size; ++i)
{
const std::size_t count = clipLine(local2view, vertices[i].vertex, vertices[i + 1].vertex, clipped);
const std::size_t count = clipLine(local2view, vertices[i], vertices[i + 1], clipped);
BestPoint(count, clipped, best, eClipCullNone);
}
}
Expand Down
11 changes: 0 additions & 11 deletions radiantcore/selection/Renderables.h
Expand Up @@ -18,17 +18,6 @@ class RenderableCircle :
{}
};

// helper class for rendering a semi-circle
class RenderableSemiCircle :
public RenderablePointVector
{
public:
// Pass the amount of points to render
RenderableSemiCircle(std::size_t size) :
RenderablePointVector(GL_LINE_STRIP, size)
{}
};

// Helper class for rendering an arrow (only the line part)
class RenderableArrowLine :
public RenderablePointVector
Expand Down
105 changes: 105 additions & 0 deletions radiantcore/selection/manipulators/Renderables.h
Expand Up @@ -3,6 +3,7 @@
#include "math/AABB.h"
#include "render/RenderableGeometry.h"
#include "render/RenderableBox.h"
#include "render.h"

namespace selection
{
Expand Down Expand Up @@ -129,4 +130,108 @@ class RenderableCornerPoints :
}
};

namespace detail
{

inline void generateQuad(std::vector<ArbitraryMeshVertex>& vertices, std::vector<unsigned int>& indices,
double size, const Vector4& colour)
{
unsigned int indexOffset = static_cast<unsigned int>(vertices.size());

vertices.push_back(ArbitraryMeshVertex({ -size, size, 0 }, { 0,0,0 }, { 0,0 }, colour));
vertices.push_back(ArbitraryMeshVertex({ size, size, 0 }, { 0,0,0 }, { 0,0 }, colour));
vertices.push_back(ArbitraryMeshVertex({ size, -size, 0 }, { 0,0,0 }, { 0,0 }, colour));
vertices.push_back(ArbitraryMeshVertex({ -size, -size, 0 }, { 0,0,0 }, { 0,0 }, colour));

indices.push_back(indexOffset + 0);
indices.push_back(indexOffset + 1);
indices.push_back(indexOffset + 1);
indices.push_back(indexOffset + 2);
indices.push_back(indexOffset + 2);
indices.push_back(indexOffset + 3);
indices.push_back(indexOffset + 3);
indices.push_back(indexOffset + 0);
}

inline Vector4 toVector4(const Colour4b& colour)
{
return
{
colour.r / 255.0,
colour.g / 255.0,
colour.b / 255.0,
colour.a / 255.0,
};
}

}

template<typename RemapPolicy>
class RenderableSemiCircle :
public render::RenderableGeometry
{
private:
constexpr static auto Segments = 8;
constexpr static auto Radius = 64.0;

const Matrix4& _localToWorld;
bool _needsUpdate;
Vector4 _colour;

std::vector<Vertex3f> _rawPoints;

public:
RenderableSemiCircle(const Matrix4& localToWorld) :
_localToWorld(localToWorld),
_needsUpdate(true),
_rawPoints((Segments << 2) + 1)
{
draw_semicircle<RemapPolicy>(Segments, Radius, _rawPoints);
}

void queueUpdate()
{
_needsUpdate = true;
}

void setColour(const Colour4b& colour)
{
_colour = detail::toVector4(colour);
queueUpdate();
}

const std::vector<Vertex3f>& getRawPoints() const
{
return _rawPoints;
}

protected:
void updateGeometry() override
{
if (!_needsUpdate) return;

_needsUpdate = false;

std::vector<ArbitraryMeshVertex> vertices;
std::vector<unsigned int> indices;

unsigned int index = 0;

for (const auto& vertex : _rawPoints)
{
vertices.push_back(ArbitraryMeshVertex(_localToWorld * vertex, { 0,0,0 }, { 0,0 }, _colour));

if (index > 0)
{
indices.push_back(index - 1);
indices.push_back(index);
}

++index;
}

RenderableGeometry::updateGeometry(render::GeometryType::Lines, vertices, indices);
}
};

}
53 changes: 41 additions & 12 deletions radiantcore/selection/manipulators/RotateManipulator.cpp
Expand Up @@ -16,24 +16,20 @@ RotateManipulator::RotateManipulator(ManipulationPivot& pivot, std::size_t segme
_rotateFree(*this),
_rotateAxis(*this),
_translatePivot(_pivotTranslatable),
_circleX((segments << 2) + 1),
_circleY((segments << 2) + 1),
_circleZ((segments << 2) + 1),
_circleX(_local2worldX),
_circleY(_local2worldY),
_circleZ(_local2worldZ),
_circleScreen(segments<<3),
_circleSphere(segments<<3),
_pivotPoint(GL_POINTS)
{
draw_semicircle<RemapYZX>(segments, radius, _circleX);
draw_semicircle<RemapZXY>(segments, radius, _circleY);
draw_semicircle<RemapXYZ>(segments, radius, _circleZ);

draw_circle<RemapXYZ>(segments, radius * 1.15f, _circleScreen);
draw_circle<RemapXYZ>(segments, radius, _circleSphere);

_pivotPoint.push_back(VertexCb(Vertex3f(0,0,0), ManipulatorBase::COLOUR_SPHERE()));
}

void RotateManipulator::UpdateColours()
void RotateManipulator::updateColours()
{
_circleX.setColour(colourSelected(COLOUR_X(), _selectableX.isSelected()));
_circleY.setColour(colourSelected(COLOUR_Y(), _selectableY.isSelected()));
Expand Down Expand Up @@ -89,13 +85,37 @@ void RotateManipulator::updateCircleTransforms()
}
}

void RotateManipulator::onPreRender(const RenderSystemPtr& renderSystem, const VolumeTest& volume)
{
if (!renderSystem)
{
clearRenderables();
return;
}

if (!_lineShader)
{
_lineShader = renderSystem->capture("$WIRE_OVERLAY");
}

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

updateColours();

_circleX.update(_lineShader);
_circleY.update(_lineShader);
_circleZ.update(_lineShader);
}

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

// temp hack
UpdateColours();
updateColours();

collector.addRenderable(*_stateOuter, _circleScreen, _pivot2World._viewpointSpace);
collector.addRenderable(*_stateOuter, _circleSphere, _pivot2World._viewpointSpace);
Expand All @@ -116,6 +136,15 @@ void RotateManipulator::render(IRenderableCollector& collector, const VolumeTest
collector.addRenderable(*_pivotPointShader, _pivotPoint, _pivot2World._worldSpace);

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

void RotateManipulator::clearRenderables()
{
_circleX.clear();
_circleY.clear();
_circleZ.clear();
_lineShader.reset();
}

std::string RotateManipulator::getRotationAxisName() const
Expand Down Expand Up @@ -162,23 +191,23 @@ void RotateManipulator::testSelect(SelectionTest& test, const Matrix4& pivot2wor
Matrix4 local2view(test.getVolume().GetViewProjection().getMultipliedBy(_local2worldX));

SelectionIntersection best;
LineStrip_BestPoint(local2view, &_circleX.front(), _circleX.size(), best);
LineStrip_BestPoint(local2view, &_circleX.getRawPoints().front(), _circleX.getRawPoints().size(), best);
selector.addSelectable(best, &_selectableX);
}

{
Matrix4 local2view(test.getVolume().GetViewProjection().getMultipliedBy(_local2worldY));

SelectionIntersection best;
LineStrip_BestPoint(local2view, &_circleY.front(), _circleY.size(), best);
LineStrip_BestPoint(local2view, &_circleY.getRawPoints().front(), _circleY.getRawPoints().size(), best);
selector.addSelectable(best, &_selectableY);
}

{
Matrix4 local2view(test.getVolume().GetViewProjection().getMultipliedBy(_local2worldZ));

SelectionIntersection best;
LineStrip_BestPoint(local2view, &_circleZ.front(), _circleZ.size(), best);
LineStrip_BestPoint(local2view, &_circleZ.getRawPoints().front(), _circleZ.getRawPoints().size(), best);
selector.addSelectable(best, &_selectableZ);
}
}
Expand Down
19 changes: 13 additions & 6 deletions radiantcore/selection/manipulators/RotateManipulator.h
Expand Up @@ -9,6 +9,7 @@
#include "selection/BasicSelectable.h"
#include "selection/ManipulationPivot.h"
#include "render.h"
#include "Renderables.h"

namespace selection
{
Expand All @@ -32,9 +33,11 @@ class RotateManipulator :
RotateAxis _rotateAxis;
TranslateFree _translatePivot;
Vector3 _axisScreen;
RenderableSemiCircle _circleX;
RenderableSemiCircle _circleY;
RenderableSemiCircle _circleZ;

RenderableSemiCircle<RemapYZX> _circleX;
RenderableSemiCircle<RemapZXY> _circleY;
RenderableSemiCircle<RemapXYZ> _circleZ;

RenderableCircle _circleScreen;
RenderableCircle _circleSphere;
RenderablePointVector _pivotPoint;
Expand All @@ -52,6 +55,8 @@ class RotateManipulator :
bool _circleY_visible;
bool _circleZ_visible;

ShaderPtr _lineShader;

public:
static ShaderPtr _stateOuter;
static ShaderPtr _pivotPointShader;
Expand All @@ -65,11 +70,10 @@ class RotateManipulator :
return Rotate;
}

void UpdateColours();
void updateCircleTransforms();

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 @@ -81,6 +85,9 @@ class RotateManipulator :
void rotate(const Quaternion& rotation) override;

private:
void updateColours();
void updateCircleTransforms();

std::string getRotationAxisName() const;
};

Expand Down

0 comments on commit 2d64d9f

Please sign in to comment.