From 18bd4f58450e47ff9d48b9cb86687a7c8575c7d6 Mon Sep 17 00:00:00 2001 From: codereader Date: Fri, 7 Jan 2022 06:37:44 +0100 Subject: [PATCH] #5584: Patch control point rendering. Selection updates are not correctly updating the view yet. --- include/igeometryrenderer.h | 1 + radiantcore/patch/PatchNode.cpp | 27 ++++++-- radiantcore/patch/PatchNode.h | 9 +-- radiantcore/patch/PatchRenderables.h | 64 +++++++++++++++++++ .../rendersystem/backend/GeometryRenderer.h | 5 +- 5 files changed, 94 insertions(+), 12 deletions(-) diff --git a/include/igeometryrenderer.h b/include/igeometryrenderer.h index 1e252c618f..3c81936b82 100644 --- a/include/igeometryrenderer.h +++ b/include/igeometryrenderer.h @@ -14,6 +14,7 @@ enum class GeometryType Triangles, Quads, Lines, + Points, }; /** diff --git a/radiantcore/patch/PatchNode.cpp b/radiantcore/patch/PatchNode.cpp index 6a3f6c106b..791ab957bd 100644 --- a/radiantcore/patch/PatchNode.cpp +++ b/radiantcore/patch/PatchNode.cpp @@ -17,7 +17,8 @@ PatchNode::PatchNode(patch::PatchDefType type) : _selectedControlVerticesNeedUpdate(true), _renderableSurfaceSolid(m_patch.getTesselation(), true), _renderableSurfaceWireframe(m_patch.getTesselation(), false), - _renderableCtrlLattice(m_patch, m_ctrl_instances) + _renderableCtrlLattice(m_patch, m_ctrl_instances), + _renderableCtrlPoints(m_patch, m_ctrl_instances) { m_patch.setFixedSubdivisions(type == patch::PatchDefType::Def3, Subdivisions(m_patch.getSubdivisions())); } @@ -41,7 +42,8 @@ PatchNode::PatchNode(const PatchNode& other) : _selectedControlVerticesNeedUpdate(true), _renderableSurfaceSolid(m_patch.getTesselation(), true), _renderableSurfaceWireframe(m_patch.getTesselation(), false), - _renderableCtrlLattice(m_patch, m_ctrl_instances) + _renderableCtrlLattice(m_patch, m_ctrl_instances), + _renderableCtrlPoints(m_patch, m_ctrl_instances) { } @@ -346,13 +348,20 @@ void PatchNode::onPreRender(const VolumeTest& volume) if (isSelected() && GlobalSelectionSystem().ComponentMode() == selection::ComponentSelectionMode::Vertex) { + updateSelectedControlVertices(); + // Selected patches in component mode render the lattice connecting the control points _renderableCtrlLattice.update(_ctrlLatticeShader); + _renderableCtrlPoints.update(_ctrlPointShader); } else { + _renderableCtrlPoints.clear(); _renderableCtrlLattice.clear(); - _renderableCtrlLattice.queueUpdate(); // will be updated next time it's rendered + + // Queue an update the next time it's rendered + _renderableCtrlPoints.queueUpdate(); + _renderableCtrlLattice.queueUpdate(); } } @@ -416,15 +425,16 @@ void PatchNode::setRenderSystem(const RenderSystemPtr& renderSystem) _renderableSurfaceSolid.clear(); _renderableSurfaceWireframe.clear(); _renderableCtrlLattice.clear(); + _renderableCtrlPoints.clear(); if (renderSystem) { - m_state_selpoint = renderSystem->capture("$SELPOINT"); + _ctrlPointShader = renderSystem->capture("$POINT"); _ctrlLatticeShader = renderSystem->capture("$LATTICE"); } else { - m_state_selpoint.reset(); + _ctrlPointShader.reset(); _ctrlLatticeShader.reset(); } } @@ -470,6 +480,7 @@ void PatchNode::updateSelectedControlVertices() const } } +#if 0 void PatchNode::renderComponentsSelected(IRenderableCollector& collector, const VolumeTest& volume) const { const_cast(m_patch).evaluateTransform(); @@ -484,6 +495,7 @@ void PatchNode::renderComponentsSelected(IRenderableCollector& collector, const collector.addRenderable(*m_state_selpoint, m_render_selected, localToWorld()); } } +#endif std::size_t PatchNode::getHighlightFlags() { @@ -547,6 +559,7 @@ void PatchNode::_onTransformationChanged() _renderableSurfaceSolid.queueUpdate(); _renderableSurfaceWireframe.queueUpdate(); _renderableCtrlLattice.queueUpdate(); + _renderableCtrlPoints.queueUpdate(); } void PatchNode::_applyTransformation() @@ -575,6 +588,7 @@ void PatchNode::onTesselationChanged() _renderableSurfaceSolid.queueUpdate(); _renderableSurfaceWireframe.queueUpdate(); _renderableCtrlLattice.queueUpdate(); + _renderableCtrlPoints.queueUpdate(); } void PatchNode::onControlPointsChanged() @@ -582,6 +596,7 @@ void PatchNode::onControlPointsChanged() _renderableSurfaceSolid.queueUpdate(); _renderableSurfaceWireframe.queueUpdate(); _renderableCtrlLattice.queueUpdate(); + _renderableCtrlPoints.queueUpdate(); } void PatchNode::onMaterialChanged() @@ -600,6 +615,7 @@ void PatchNode::onVisibilityChanged(bool visible) _renderableSurfaceSolid.clear(); _renderableSurfaceWireframe.clear(); _renderableCtrlLattice.clear(); + _renderableCtrlPoints.clear(); } else { @@ -607,5 +623,6 @@ void PatchNode::onVisibilityChanged(bool visible) _renderableSurfaceSolid.queueUpdate(); _renderableSurfaceWireframe.queueUpdate(); _renderableCtrlLattice.queueUpdate(); + _renderableCtrlPoints.queueUpdate(); } } diff --git a/radiantcore/patch/PatchNode.h b/radiantcore/patch/PatchNode.h index b973159fed..6820679797 100644 --- a/radiantcore/patch/PatchNode.h +++ b/radiantcore/patch/PatchNode.h @@ -40,7 +40,7 @@ class PatchNode final : // An internal AABB variable to calculate the bounding box of the selected components (has to be mutable) mutable AABB m_aabb_component; - ShaderPtr m_state_selpoint; + ShaderPtr _ctrlPointShader; ShaderPtr _ctrlLatticeShader; // For pivoted rotations, we need a copy of this lying around @@ -52,9 +52,8 @@ class PatchNode final : RenderablePatchTesselation _renderableSurfaceSolid; RenderablePatchTesselation _renderableSurfaceWireframe; - - // Draws the wireframe connecting the control points - RenderablePatchLattice _renderableCtrlLattice; + RenderablePatchLattice _renderableCtrlLattice; // Wireframe connecting the control points + RenderablePatchControlPoints _renderableCtrlPoints; // the coloured control points public: PatchNode(patch::PatchDefType type); @@ -169,8 +168,10 @@ class PatchNode final : // rendered as highlighted. void updateSelectedControlVertices() const; +#if 0 // greebo: Renders the selected components. This is called by the above two render functions void renderComponentsSelected(IRenderableCollector& collector, const VolumeTest& volume) const; +#endif }; typedef std::shared_ptr PatchNodePtr; typedef std::weak_ptr PatchNodeWeakPtr; diff --git a/radiantcore/patch/PatchRenderables.h b/radiantcore/patch/PatchRenderables.h index 9705007075..1b1594314c 100644 --- a/radiantcore/patch/PatchRenderables.h +++ b/radiantcore/patch/PatchRenderables.h @@ -290,3 +290,67 @@ class RenderablePatchLattice : RenderableGeometry::updateGeometry(render::GeometryType::Lines, vertices, indices); } }; + +// Represents the set of coloured points used to manipulate the control point matrix +class RenderablePatchControlPoints : + public render::RenderableGeometry +{ +private: + bool _needsUpdate; + + const IPatch& _patch; + const std::vector& _controlPoints; + +public: + RenderablePatchControlPoints(const IPatch& patch, const std::vector& controlPoints) : + _patch(patch), + _controlPoints(controlPoints), + _needsUpdate(true) + {} + + void queueUpdate() + { + _needsUpdate = true; + } + +protected: + void updateGeometry() override + { + if (!_needsUpdate) return; + + _needsUpdate = false; + + // Generate the new point vector + std::vector vertices; + std::vector indices; + + vertices.reserve(_controlPoints.size()); + indices.reserve(_controlPoints.size()); + + static const Vector4 SelectedColour(0, 0, 0, 1); + auto width = _patch.getWidth(); + + for (std::size_t i = 0; i < _controlPoints.size(); ++i) + { + const auto& ctrl = _controlPoints[i]; + + vertices.push_back(ArbitraryMeshVertex(ctrl.control.vertex, { 0, 0, 0 }, { 0, 0 }, + ctrl.isSelected() ? SelectedColour : getColour(i, width))); + indices.push_back(static_cast(i)); + } + + RenderableGeometry::updateGeometry(render::GeometryType::Points, vertices, indices); + } + +private: + inline const Vector4 getColour(std::size_t i, std::size_t width) + { + static const Vector3& cornerColourVec = GlobalPatchModule().getSettings().getVertexColour(patch::PatchEditVertexType::Corners); + static const Vector3& insideColourVec = GlobalPatchModule().getSettings().getVertexColour(patch::PatchEditVertexType::Inside); + + const Vector4 colour_corner(cornerColourVec, 1); + const Vector4 colour_inside(insideColourVec, 1); + + return (i % 2 || (i / width) % 2) ? colour_inside : colour_corner; + } +}; diff --git a/radiantcore/rendersystem/backend/GeometryRenderer.h b/radiantcore/rendersystem/backend/GeometryRenderer.h index be0fad6123..5475156c33 100644 --- a/radiantcore/rendersystem/backend/GeometryRenderer.h +++ b/radiantcore/rendersystem/backend/GeometryRenderer.h @@ -132,6 +132,7 @@ class GeometryRenderer : _buffers.emplace_back(GL_TRIANGLES); _buffers.emplace_back(GL_QUADS); _buffers.emplace_back(GL_LINES); + _buffers.emplace_back(GL_POINTS); } bool empty() const @@ -220,9 +221,7 @@ class GeometryRenderer : glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - - // Render this slot without any vertex colours - glDisableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); glFrontFace(GL_CW);