diff --git a/libs/render.h b/libs/render.h index 84eb5f3d3a..a60bd7d2a5 100644 --- a/libs/render.h +++ b/libs/render.h @@ -404,7 +404,7 @@ class RemapZXY // VertexArray must expose a value_type typedef and implement an index operator[], like std::vector template -inline void draw_ellipse(const std::size_t numSegments, const float radiusX, const float radiusY, VertexArray& vertices) +inline void draw_ellipse(const std::size_t numSegments, const float radiusX, const float radiusY, VertexArray& vertices, std::size_t firstVertex = 0) { // Per half circle we push in (Segments x 4) vertices (the caller made room for that) const auto numVerticesPerHalf = numSegments << 2; @@ -417,8 +417,8 @@ inline void draw_ellipse(const std::size_t numSegments, const float radiusX, con auto x = radiusX * cos(curAngle); auto y = radiusY * sin(curAngle); - remap_policy::set(vertices[curSegment], x, y, 0); - remap_policy::set(vertices[curSegment + numVerticesPerHalf], -x, -y, 0); + remap_policy::set(vertices[firstVertex + curSegment], x, y, 0); + remap_policy::set(vertices[firstVertex + curSegment + numVerticesPerHalf], -x, -y, 0); } } @@ -457,9 +457,9 @@ inline void draw_semicircle(const std::size_t segments, const float radius, Vert } template -inline void draw_circle(const std::size_t segments, const float radius, VertexArray& vertices) +inline void draw_circle(const std::size_t segments, const float radius, VertexArray& vertices, std::size_t firstVertex = 0) { - draw_ellipse(segments, radius, radius, vertices); + draw_ellipse(segments, radius, radius, vertices, firstVertex); } inline void draw_quad(const float radius, VertexCb* quad) { diff --git a/radiantcore/entity/speaker/SpeakerNode.cpp b/radiantcore/entity/speaker/SpeakerNode.cpp index 7f424d0ba3..d51ef08920 100644 --- a/radiantcore/entity/speaker/SpeakerNode.cpp +++ b/radiantcore/entity/speaker/SpeakerNode.cpp @@ -243,38 +243,50 @@ void SpeakerNode::onPreRender(const VolumeTest& volume) EntityNode::onPreRender(volume); _renderableBox.update(getColourShader()); + + if (isSelected() || EntitySettings::InstancePtr()->getShowAllSpeakerRadii()) + { + _renderableRadiiWireframe.update(getWireShader()); + } + else + { + _renderableRadiiWireframe.clear(); + } } void SpeakerNode::renderSolid(IRenderableCollector& collector, const VolumeTest& volume) const { EntityNode::renderSolid(collector, volume); - +#if 0 // Submit the speaker radius if we are selected or the "show all speaker // radii" option is set if (isSelected() || EntitySettings::InstancePtr()->getShowAllSpeakerRadii()) { collector.addRenderable(*getFillShader(), _renderableRadiiWireframe, localToWorld()); } +#endif } void SpeakerNode::renderWireframe(IRenderableCollector& collector, const VolumeTest& volume) const { EntityNode::renderWireframe(collector, volume); - +#if 0 // Submit the speaker radius if we are selected or the "show all speaker // radii" option is set if (isSelected() || EntitySettings::InstancePtr()->getShowAllSpeakerRadii()) { collector.addRenderable(*getWireShader(), _renderableRadiiWireframe, localToWorld()); } +#endif } void SpeakerNode::renderHighlights(IRenderableCollector& collector, const VolumeTest& volume) { - EntityNode::renderHighlights(collector, volume); - collector.addHighlightRenderable(_renderableBox, Matrix4::getIdentity()); + collector.addHighlightRenderable(_renderableRadiiWireframe, Matrix4::getIdentity()); + + EntityNode::renderHighlights(collector, volume); } void SpeakerNode::setRenderSystem(const RenderSystemPtr& renderSystem) @@ -283,6 +295,7 @@ void SpeakerNode::setRenderSystem(const RenderSystemPtr& renderSystem) // Clear the geometry from any previous shader _renderableBox.clear(); + _renderableRadiiWireframe.clear(); } void SpeakerNode::translate(const Vector3& translation) @@ -296,6 +309,7 @@ void SpeakerNode::updateTransform() transformChanged(); _renderableBox.queueUpdate(); + _renderableRadiiWireframe.queueUpdate(); } void SpeakerNode::updateAABB() diff --git a/radiantcore/entity/speaker/SpeakerNode.h b/radiantcore/entity/speaker/SpeakerNode.h index 1fd86fd99a..ac821a8d6b 100644 --- a/radiantcore/entity/speaker/SpeakerNode.h +++ b/radiantcore/entity/speaker/SpeakerNode.h @@ -117,6 +117,11 @@ class SpeakerNode final : void renderHighlights(IRenderableCollector& collector, const VolumeTest& volume); void setRenderSystem(const RenderSystemPtr& renderSystem) override; + bool isOriented() const override + { + return false; // speaker representation is rendered in world coordinates + } + void selectedChangedComponent(const ISelectable& selectable); protected: diff --git a/radiantcore/entity/speaker/SpeakerRenderables.cpp b/radiantcore/entity/speaker/SpeakerRenderables.cpp index 1bd15ae460..220950f442 100644 --- a/radiantcore/entity/speaker/SpeakerRenderables.cpp +++ b/radiantcore/entity/speaker/SpeakerRenderables.cpp @@ -1,5 +1,7 @@ #include "SpeakerRenderables.h" +#include "render.h" + // the drawing functions void sphereDrawFill(const Vector3& origin, float radius, int sides) @@ -183,15 +185,32 @@ void RenderableSpeakerRadiiWireframe::updateGeometry() _needsUpdate = false; // Generate the three circles in axis-aligned planes -#if 0 + const std::size_t NumSegments = 2; + + std::vector vertices; + // Allocate space for 3 circles, each has NumSegments * 8 vertices + vertices.resize(1 * (NumSegments << 3)); + + draw_circle(NumSegments, _radii.getMax(), vertices, 0); + + // Generate the indices, walking around the vertices + std::vector indices; + auto numVertices = vertices.size(); + indices.reserve(numVertices << 1); // 2 indices per vertex + + for (auto i = 0; i < numVertices; ++i) + { + indices.push_back(i); + indices.push_back((i + 1) % numVertices); // wrap around the last index to point at 0 again + } + // Move the points to their world position for (auto& vertex : vertices) { - vertex.vertex += _worldPos; + vertex.vertex += _origin; } - RenderableGeometry::updateGeometry(render::GeometryType::Lines, vertices, WireframeBoxIndices); -#endif + RenderableGeometry::updateGeometry(render::GeometryType::Lines, vertices, indices); } #if 0