diff --git a/radiantcore/entity/target/RenderableTargetLines.h b/radiantcore/entity/target/RenderableTargetLines.h index e30db1bd89..beb31e6d21 100644 --- a/radiantcore/entity/target/RenderableTargetLines.h +++ b/radiantcore/entity/target/RenderableTargetLines.h @@ -31,16 +31,16 @@ class RenderableTargetLines : bool _needsUpdate; ShaderPtr _shader; render::IGeometryRenderer::Slot _surfaceSlot; - std::size_t _numTargets; + std::size_t _numVisibleLines; public: - RenderableTargetLines(const TargetKeyCollection& targetKeys) : - RenderablePointVector(GL_LINES), - _targetKeys(targetKeys), + RenderableTargetLines(const TargetKeyCollection& targetKeys) : + RenderablePointVector(GL_LINES), + _targetKeys(targetKeys), _needsUpdate(true), _surfaceSlot(render::IGeometryRenderer::InvalidSlot), - _numTargets(0) - {} + _numVisibleLines(0) + {} bool hasTargets() const { @@ -61,32 +61,26 @@ class RenderableTargetLines : _shader.reset(); _surfaceSlot = render::IGeometryRenderer::InvalidSlot; - _numTargets = 0; + _numVisibleLines = 0; } void update(const ShaderPtr& shader, const Vector3& worldPosition) { - bool shaderChanged = _shader != shader; - - if (!_needsUpdate && !shaderChanged) return; + // Target lines are visible if both their start and end entities are visible + // This is hard to track in the scope of this class, so we fall back to doing + // an update on the renderable geometry every frame + auto shaderChanged = _shader != shader; _needsUpdate = false; - auto sizeChanged = _numTargets != _targetKeys.getNumTargets(); - if (_shader && _surfaceSlot != render::IGeometryRenderer::InvalidSlot && (shaderChanged || sizeChanged)) - { - clear(); - } - - _shader = shader; - _numTargets = _targetKeys.getNumTargets(); - // Collect vertex and index data std::vector vertices; std::vector indices; + auto maxTargets = _targetKeys.getNumTargets(); + auto numVisibleLines = 0; - vertices.reserve(6 * _numTargets); - indices.reserve(6 * _numTargets); + vertices.reserve(6 * maxTargets); + indices.reserve(6 * maxTargets); _targetKeys.forEachTarget([&](const TargetPtr& target) { @@ -95,11 +89,21 @@ class RenderableTargetLines : return; } + numVisibleLines++; auto targetPosition = target->getPosition(); addTargetLine(worldPosition, targetPosition, vertices, indices); }); + // Size or shader changes both require detaching our geometry first + if (_shader && _surfaceSlot != render::IGeometryRenderer::InvalidSlot && (shaderChanged || numVisibleLines != _numVisibleLines)) + { + clear(); + } + + _shader = shader; + _numVisibleLines = numVisibleLines; + if (_surfaceSlot == render::IGeometryRenderer::InvalidSlot) { _surfaceSlot = shader->addGeometry(render::GeometryType::Lines, vertices, indices); @@ -183,7 +187,7 @@ class RenderableTargetLines : Vector3 xyPoint1 = arrowBase + xyDir; Vector3 xyPoint2 = arrowBase - xyDir; - auto indexOffset = vertices.size(); + auto indexOffset = static_cast(vertices.size()); // The line from this to the other entity vertices.push_back(ArbitraryMeshVertex(startPosition, { 1,0,0 }, { 0, 0 })); diff --git a/radiantcore/rendersystem/backend/GeometryRenderer.h b/radiantcore/rendersystem/backend/GeometryRenderer.h index 34b0ce9a34..608fcae557 100644 --- a/radiantcore/rendersystem/backend/GeometryRenderer.h +++ b/radiantcore/rendersystem/backend/GeometryRenderer.h @@ -139,6 +139,7 @@ class GeometryRenderer : { _buffers.emplace_back(GL_TRIANGLES); _buffers.emplace_back(GL_QUADS); + _buffers.emplace_back(GL_LINES); } bool empty() const @@ -236,7 +237,14 @@ class GeometryRenderer : private: constexpr static std::uint8_t GetBucketIndexForIndexType(GeometryType indexType) { - return indexType == GeometryType::Triangles ? 0 : 1; + switch (indexType) + { + case GeometryType::Triangles: return 0; + case GeometryType::Quads: return 1; + case GeometryType::Lines: return 2; + } + + return 0; } VertexBuffer& getBucketByIndex(std::uint8_t bucketIndex)