From 3b8049d226c008e403c28a1b12e5e1285cee3bd7 Mon Sep 17 00:00:00 2001 From: pierow Date: Mon, 29 Apr 2024 17:24:47 -0400 Subject: [PATCH] fix crosshair circle rendering issues and added round dot option --- main/source/cl_dll/hud_crosshairs.cpp | 67 +++++++++++++++++++++------ main/source/cl_dll/hud_crosshairs.h | 10 ++++ main/source/cl_dll/hudgl.cpp | 43 +++++++++++++---- main/source/cl_dll/hudgl.h | 10 +--- 4 files changed, 98 insertions(+), 32 deletions(-) diff --git a/main/source/cl_dll/hud_crosshairs.cpp b/main/source/cl_dll/hud_crosshairs.cpp index 8c4f8802..375b1375 100644 --- a/main/source/cl_dll/hud_crosshairs.cpp +++ b/main/source/cl_dll/hud_crosshairs.cpp @@ -31,6 +31,7 @@ int CHudCrosshairs::Init() cl_cross_dot_alpha = CVAR_CREATE("cl_cross_dot_alpha", "", FCVAR_ARCHIVE); cl_cross_dot_outline = CVAR_CREATE("cl_cross_dot_outline", "0", FCVAR_ARCHIVE); cl_cross_dot_outline_alpha = CVAR_CREATE("cl_cross_dot_outline_alpha", "", FCVAR_ARCHIVE); + cl_cross_dot_round = CVAR_CREATE("cl_cross_dot_round", "0", FCVAR_ARCHIVE); cl_cross_line_top = CVAR_CREATE("cl_cross_line_top", "1", FCVAR_ARCHIVE); cl_cross_line_bottom = CVAR_CREATE("cl_cross_line_bottom", "1", FCVAR_ARCHIVE); cl_cross_line_left = CVAR_CREATE("cl_cross_line_left", "1", FCVAR_ARCHIVE); @@ -77,7 +78,7 @@ int CHudCrosshairs::Draw(float time) if (cl_cross_scaling->value != 0) { // Scale from 1080 Y res, as it's what the default crosshairs are designed for, but don't scale when resolution is close to 1080, as it looks bad. - const float screenscale = ScreenHeight() / 1080.0f; //ScreenHeight() * 0.000926f + const float screenscale = ScreenHeight() / 1080; //ScreenHeight() * 0.000926f // Lowering scale looks like junk, don't bother. //if (screenscale < 0.75f) //{ @@ -197,10 +198,27 @@ int CHudCrosshairs::Draw(float time) gl.color(0, 0, 0, dotoutalpha); - float size = min(cl_cross_dot_size->value * scalar, ScreenHeight() * 0.2f) + (dotout * 2.0f); - Vector2D offset = Vector2D(size / 2.0f, size / 2.0f); + float size = min(cl_cross_dot_size->value * scalar, ScreenHeight() * 0.2f); + + if (cl_cross_dot_round->value) + { + size *= 0.5f; + if (old_round_dot_outline_radius != size || old_round_dot_outline_thickness != dotout) { + // Recompute the circle points. + round_dot_outline_points = HudGL::compute_circle(size + (dotout * 0.5f), dotout); + old_round_dot_outline_radius = size; + old_round_dot_outline_thickness = dotout; + } - gl.rectangle(center - offset, center + offset); + gl.circle(center, round_dot_outline_points); + } + else + { + //TOFIX - Not a true outline, will be seen behind transparent dots + size += dotout * 2.0f; + Vector2D offset = Vector2D(size / 2.0f, size / 2.0f); + gl.rectangle(center - offset, center + offset); + } } float circleout; @@ -225,22 +243,26 @@ int CHudCrosshairs::Draw(float time) auto radius = cl_cross_circle_radius->value * scalar; + float thickness; + if (!circleoutinner) { radius += cl_cross_circle_thickness->value * scalar * 0.5f; - gl.line_width(circleout); + thickness = circleout; } else { - gl.line_width(cl_cross_circle_thickness->value * scalar + (circleout * 2.0f)); + //TOFIX - Not a true outline, will be seen behind transparent circles + thickness = cl_cross_circle_thickness->value * scalar + (circleout * 2.0f); } - if (old_circle_radius != radius) { + if (old_circle_outline_radius != radius || old_circle_outline_thickness != thickness) { // Recompute the circle points. - circle_points = HudGL::compute_circle(radius); - old_circle_radius = radius; + circle_outline_points = HudGL::compute_circle(radius, thickness); + old_circle_outline_radius = radius; + old_circle_outline_thickness = thickness; } - gl.circle(center, circle_points); + gl.circle(center, circle_outline_points); } gl.color(r, g, b, alpha); @@ -298,14 +320,15 @@ int CHudCrosshairs::Draw(float time) { gl.color(r, g, b, circlealpha); } - - gl.line_width(cl_cross_circle_thickness->value * scalar); float radius = cl_cross_circle_radius->value * scalar; - if (old_circle_radius != radius) { + float thickness = cl_cross_circle_thickness->value * scalar; + if (old_circle_radius != radius || old_circle_thickness != thickness) { // Recompute the circle points. - circle_points = HudGL::compute_circle(radius); + circle_points = HudGL::compute_circle(radius, thickness); old_circle_radius = radius; + old_circle_thickness = thickness; + gEngfuncs.Con_Printf("radius:%f thickness:%f\n", radius, thickness); } gl.circle(center, circle_points); @@ -332,7 +355,21 @@ int CHudCrosshairs::Draw(float time) float size = min(cl_cross_dot_size->value * scalar, ScreenHeight() * 0.2f); Vector2D offset = Vector2D(size / 2.0f, size / 2.0f); - gl.rectangle(center - offset, center + offset); + if (cl_cross_dot_round->value) + { + size *= 0.5f; + if (old_round_dot_radius != size) { + // Recompute the circle points. + round_dot_points = HudGL::compute_circle(size); + old_round_dot_radius = size; + } + + gl.round_dot(center, round_dot_points); + } + else + { + gl.rectangle(center - offset, center + offset); + } } return 0; diff --git a/main/source/cl_dll/hud_crosshairs.h b/main/source/cl_dll/hud_crosshairs.h index 3c8f3b27..5952d839 100644 --- a/main/source/cl_dll/hud_crosshairs.h +++ b/main/source/cl_dll/hud_crosshairs.h @@ -27,6 +27,7 @@ class CHudCrosshairs : public CHudBase cvar_t* cl_cross_dot_alpha; cvar_t* cl_cross_dot_outline; cvar_t* cl_cross_dot_outline_alpha; + cvar_t* cl_cross_dot_round; cvar_t* cl_cross_line_top; cvar_t* cl_cross_line_bottom; cvar_t* cl_cross_line_left; @@ -34,7 +35,16 @@ class CHudCrosshairs : public CHudBase cvar_t* cl_cross_scaling; float old_circle_radius; + float old_circle_thickness; std::vector circle_points; + float old_circle_outline_radius; + float old_circle_outline_thickness; + std::vector circle_outline_points; + float old_round_dot_radius; + std::vector round_dot_points; + float old_round_dot_outline_radius; + float old_round_dot_outline_thickness; + std::vector round_dot_outline_points; public: virtual int Init(); diff --git a/main/source/cl_dll/hudgl.cpp b/main/source/cl_dll/hudgl.cpp index e9b2f9ad..a1c15c81 100644 --- a/main/source/cl_dll/hudgl.cpp +++ b/main/source/cl_dll/hudgl.cpp @@ -52,11 +52,21 @@ void HudGL::line(const Vector2D& start, const Vector2D& end) const { glEnd(); } -//#ifdef __APPLE__ -////Remove when OSX builds with c++11 -//#else void HudGL::circle(const Vector2D& center, const std::vector& points) const { - glBegin(GL_LINE_STRIP); + glBegin(GL_TRIANGLE_STRIP); + + for (const Vector2D& point : points) + glVertex2f(center.x + point.x, center.y + point.y); + + glVertex2f(center.x + points[0].x, center.y + points[0].y); + glVertex2f(center.x + points[1].x, center.y + points[1].y); + glEnd(); +} + +void HudGL::round_dot(const Vector2D& center, const std::vector& points) const { + glBegin(GL_TRIANGLE_FAN); + + glVertex2f(center.x, center.y); for (const Vector2D& point : points) glVertex2f(center.x + point.x, center.y + point.y); @@ -64,7 +74,6 @@ void HudGL::circle(const Vector2D& center, const std::vector& points) glVertex2f(center.x + points[0].x, center.y + points[0].y); glEnd(); } -//#endif void HudGL::rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const { glBegin(GL_QUADS); @@ -75,9 +84,6 @@ void HudGL::rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const glEnd(); } -//#ifdef __APPLE__ -////Remove when OSX builds with c++11 -//#else std::vector HudGL::compute_circle(float radius) { // Maximum allowed distance between the circle and the rendered line segment. const float MAX_ERROR = 0.1f; @@ -94,4 +100,23 @@ std::vector HudGL::compute_circle(float radius) { return points; } -//#endif \ No newline at end of file + +std::vector HudGL::compute_circle(float radius, float thickness) { + // Maximum allowed distance between the circle and the rendered line segment. + const float MAX_ERROR = 0.1f; + const unsigned segment_count = + static_cast(std::ceil(M_PI / std::acos((radius - MAX_ERROR) / radius))); + const unsigned point_count = segment_count * 2; + float half_thickness = thickness * 0.5f; + + std::vector points; + points.reserve(point_count); + + for (unsigned i = 0; i < segment_count; ++i) { + float angle = static_cast(M_PI * 2 * i / segment_count); + points.emplace_back((radius + half_thickness) * std::cos(angle), (radius + half_thickness) * std::sin(angle)); + points.emplace_back((radius - half_thickness) * std::cos(angle), (radius - half_thickness) * std::sin(angle)); + } + + return points; +} diff --git a/main/source/cl_dll/hudgl.h b/main/source/cl_dll/hudgl.h index 4fe3137b..4fccc2b7 100644 --- a/main/source/cl_dll/hudgl.h +++ b/main/source/cl_dll/hudgl.h @@ -9,16 +9,10 @@ public: void color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const; void line_width(float width) const; void line(const Vector2D& start, const Vector2D& end) const; -//#ifdef __APPLE__ -// //Remove when OSX builds with c++11 -//#else void circle(const Vector2D& center, const std::vector& points) const; -//#endif + void round_dot(const Vector2D& center, const std::vector& points) const; void rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const; -//#ifdef __APPLE__ -// //Remove when OSX builds with c++11 -//#else static std::vector compute_circle(float radius); -//#endif + static std::vector compute_circle(float radius, float thickness); };