From 87de86f7d19aba5cb16c675a3b0ee8142da72bd7 Mon Sep 17 00:00:00 2001 From: Bart Trzynadlowski Date: Fri, 17 Mar 2023 23:00:44 -0700 Subject: [PATCH] Crosshair: use actual adjusted viewport resolution (configuration resolution is not the same thing). Fixes crosshair alignment for resolutions with non-Model 3 aspect. --- Src/OSD/SDL/Crosshair.cpp | 537 +++++++++++++++++++------------------- Src/OSD/SDL/Crosshair.h | 84 +++--- Src/OSD/SDL/Main.cpp | 6 +- 3 files changed, 315 insertions(+), 312 deletions(-) diff --git a/Src/OSD/SDL/Crosshair.cpp b/Src/OSD/SDL/Crosshair.cpp index d9d0c32..d5354b5 100644 --- a/Src/OSD/SDL/Crosshair.cpp +++ b/Src/OSD/SDL/Crosshair.cpp @@ -1,7 +1,7 @@ /** ** Supermodel ** A Sega Model 3 Arcade Emulator. - ** Copyright 2003-2022 The Supermodel Team + ** Copyright 2003-2023 The Supermodel Team ** ** This file is part of Supermodel. ** @@ -31,305 +31,310 @@ bool CCrosshair::Init() { - const std::string p1CrosshairFile = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Assets) << "p1crosshair.bmp"; - const std::string p2CrosshairFile = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Assets) << "p2crosshair.bmp"; + const std::string p1CrosshairFile = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Assets) << "p1crosshair.bmp"; + const std::string p2CrosshairFile = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Assets) << "p2crosshair.bmp"; - m_crosshairStyle = Util::ToLower(m_config["CrosshairStyle"].ValueAs()); - if (m_crosshairStyle == "bmp") - m_isBitmapCrosshair = true; - else if (m_crosshairStyle == "vector") - m_isBitmapCrosshair = false; + m_crosshairStyle = Util::ToLower(m_config["CrosshairStyle"].ValueAs()); + if (m_crosshairStyle == "bmp") + m_isBitmapCrosshair = true; + else if (m_crosshairStyle == "vector") + m_isBitmapCrosshair = false; + else + { + ErrorLog("Invalid crosshair style '%s', must be 'vector' or 'bmp'. Reverting to 'vector'.\n", m_crosshairStyle.c_str()); + m_isBitmapCrosshair = false; + } + + SDL_Surface* surfaceCrosshairP1 = SDL_LoadBMP(p1CrosshairFile.c_str()); + SDL_Surface* surfaceCrosshairP2 = SDL_LoadBMP(p2CrosshairFile.c_str()); + if (surfaceCrosshairP1 == NULL || surfaceCrosshairP2 == NULL) + return FAIL; + + m_p1CrosshairW = surfaceCrosshairP1->w; + m_p1CrosshairH = surfaceCrosshairP1->h; + m_p2CrosshairW = surfaceCrosshairP2->w; + m_p2CrosshairH = surfaceCrosshairP2->h; + + glGenTextures(2, m_crosshairTexId); + + glBindTexture(GL_TEXTURE_2D, m_crosshairTexId[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_p1CrosshairW, m_p1CrosshairH, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceCrosshairP1->pixels); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, m_crosshairTexId[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_p1CrosshairW, m_p1CrosshairH, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceCrosshairP2->pixels); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, 0); + + SDL_FreeSurface(surfaceCrosshairP1); + SDL_FreeSurface(surfaceCrosshairP2); + + // Get DPI + SDL_GetDisplayDPI(0, &m_diagDpi, &m_hDpi, &m_vDpi); + m_dpiMultiplicator = m_hDpi / m_standardDpi; // note : on linux VM diagdpi returns 0 + + // 3d obj + m_uvCoord.emplace_back(0.0f, 0.0f); + m_uvCoord.emplace_back(1.0f, 0.0f); + m_uvCoord.emplace_back(1.0f, 1.0f); + m_uvCoord.emplace_back(0.0f, 0.0f); + m_uvCoord.emplace_back(1.0f, 1.0f); + m_uvCoord.emplace_back(0.0f, 1.0f); + + m_vertexShader = R"glsl( + + #version 410 core + + uniform mat4 mvp; + layout(location = 0) in vec3 inVertices; + layout(location = 1) in vec2 vertexUV; + out vec2 UV; + + void main(void) + { + gl_Position = mvp * vec4(inVertices,1.0); + UV = vertexUV; + } + )glsl"; + + m_fragmentShader = R"glsl( + + #version 410 core + + uniform vec4 colour; + uniform sampler2D CrosshairTexture; + uniform bool isBitmap; + out vec4 fragColour; + in vec2 UV; + + void main(void) + { + if (!isBitmap) + fragColour = colour; else + fragColour = colour * texture(CrosshairTexture, UV); + } + )glsl"; + + m_shader.LoadShaders(m_vertexShader, m_fragmentShader); + m_shader.GetUniformLocationMap("mvp"); + m_shader.GetUniformLocationMap("CrosshairTexture"); + m_shader.GetUniformLocationMap("colour"); + m_shader.GetUniformLocationMap("isBitmap"); + + m_vbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(BasicVertex) * (MaxVerts)); + m_vbo.Bind(true); + m_textvbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(UVCoords) * (int)m_uvCoord.size()); + m_textvbo.Bind(true); + + glGenVertexArrays(1, &m_vao); + glBindVertexArray(m_vao); + + m_vbo.Bind(true); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(BasicVertex), 0); + m_vbo.Bind(false); + + m_textvbo.Bind(true); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(UVCoords), 0); + m_textvbo.Bind(false); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + glBindVertexArray(0); + + return OKAY; +} + +void CCrosshair::BuildCrosshairVertices(unsigned int xRes, unsigned int yRes) +{ + float aspect = (float)xRes / (float)yRes; + m_verts.clear(); + if (!m_isBitmapCrosshair) + { + m_verts.emplace_back(0.0f, m_dist); // bottom triangle + m_verts.emplace_back(m_base / 2.0f, (m_dist + m_height) * aspect); + m_verts.emplace_back(-m_base / 2.0f, (m_dist + m_height) * aspect); + m_verts.emplace_back(0.0f, -m_dist); // top triangle + m_verts.emplace_back(-m_base / 2.0f, -(m_dist + m_height) * aspect); + m_verts.emplace_back(m_base / 2.0f, -(m_dist + m_height) * aspect); + m_verts.emplace_back(-m_dist, 0.0f); // left triangle + m_verts.emplace_back(-m_dist - m_height, (m_base / 2.0f) * aspect); + m_verts.emplace_back(-m_dist - m_height, -(m_base / 2.0f) * aspect); + m_verts.emplace_back(m_dist, 0.0f); // right triangle + m_verts.emplace_back(m_dist + m_height, -(m_base / 2.0f) * aspect); + m_verts.emplace_back(m_dist + m_height, (m_base / 2.0f) * aspect); + } + else + { + m_verts.emplace_back(-m_squareSize / 2.0f, -m_squareSize / 2.0f * aspect); + m_verts.emplace_back(m_squareSize / 2.0f, -m_squareSize / 2.0f * aspect); + m_verts.emplace_back(m_squareSize / 2.0f, m_squareSize / 2.0f * aspect); + m_verts.emplace_back(-m_squareSize / 2.0f, -m_squareSize / 2.0f * aspect); + m_verts.emplace_back(m_squareSize / 2.0f, m_squareSize / 2.0f * aspect); + m_verts.emplace_back(-m_squareSize / 2.0f, m_squareSize / 2.0f * aspect); + } +} + +void CCrosshair::DrawCrosshair(New3D::Mat4 matrix, float x, float y, int player, unsigned int xRes, unsigned int yRes) +{ + BuildCrosshairVertices(xRes, yRes); + + float r=0.0f, g=0.0f, b=0.0f; + int count = (int)m_verts.size(); + + if (count > MaxVerts) + { + count = MaxVerts; // maybe we could error out somehow + } + + m_shader.EnableShader(); + matrix.Translate(x, y, 0); + + if (!m_isBitmapCrosshair) + { + switch (player) { - ErrorLog("Invalid crosshair style '%s', must be 'vector' or 'bmp'. Reverting to 'vector'.\n", m_crosshairStyle.c_str()); - m_isBitmapCrosshair = false; + case 0: // P1 red color + r = 1.0f; + g = 0.0f; + b = 0.0f; + break; + case 1: // P2 green color + r = 0.0f; + g = 1.0f; + b = 0.0f; + break; } - m_xRes = m_config["XResolution"].ValueAs(); - m_yRes = m_config["YResolution"].ValueAs(); - m_a = (float)m_xRes / (float)m_yRes; + matrix.Scale(m_dpiMultiplicator, m_dpiMultiplicator, 0); - SDL_Surface* surfaceCrosshairP1 = SDL_LoadBMP(p1CrosshairFile.c_str()); - SDL_Surface* surfaceCrosshairP2 = SDL_LoadBMP(p2CrosshairFile.c_str()); - if (surfaceCrosshairP1 == NULL || surfaceCrosshairP2 == NULL) - return FAIL; + // update uniform memory + glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, matrix); + glUniform4f(m_shader.uniformLocMap["colour"], r, g, b, 1.0f); + glUniform1i(m_shader.uniformLocMap["isBitmap"], false); - m_p1CrosshairW = surfaceCrosshairP1->w; - m_p1CrosshairH = surfaceCrosshairP1->h; - m_p2CrosshairW = surfaceCrosshairP2->w; - m_p2CrosshairH = surfaceCrosshairP2->h; - - glGenTextures(2, m_crosshairTexId); - - glBindTexture(GL_TEXTURE_2D, m_crosshairTexId[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_p1CrosshairW, m_p1CrosshairH, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceCrosshairP1->pixels); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glBindTexture(GL_TEXTURE_2D, m_crosshairTexId[1]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_p1CrosshairW, m_p1CrosshairH, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceCrosshairP2->pixels); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glBindTexture(GL_TEXTURE_2D, 0); - - SDL_FreeSurface(surfaceCrosshairP1); - SDL_FreeSurface(surfaceCrosshairP2); - - // Get DPI - SDL_GetDisplayDPI(0, &m_diagDpi, &m_hDpi, &m_vDpi); - m_dpiMultiplicator = m_hDpi / m_standardDpi; // note : on linux VM diagdpi returns 0 - - // 3d obj - m_uvCoord.emplace_back(0.0f, 0.0f); - m_uvCoord.emplace_back(1.0f, 0.0f); - m_uvCoord.emplace_back(1.0f, 1.0f); - m_uvCoord.emplace_back(0.0f, 0.0f); - m_uvCoord.emplace_back(1.0f, 1.0f); - m_uvCoord.emplace_back(0.0f, 1.0f); - - if (!m_isBitmapCrosshair) - { - m_verts.emplace_back(0.0f, m_dist); // bottom triangle - m_verts.emplace_back(m_base / 2.0f, (m_dist + m_height) * m_a); - m_verts.emplace_back(-m_base / 2.0f, (m_dist + m_height) * m_a); - m_verts.emplace_back(0.0f, -m_dist); // top triangle - m_verts.emplace_back(-m_base / 2.0f, -(m_dist + m_height) * m_a); - m_verts.emplace_back(m_base / 2.0f, -(m_dist + m_height) * m_a); - m_verts.emplace_back(-m_dist, 0.0f); // left triangle - m_verts.emplace_back(-m_dist - m_height, (m_base / 2.0f) * m_a); - m_verts.emplace_back(-m_dist - m_height, -(m_base / 2.0f) * m_a); - m_verts.emplace_back(m_dist, 0.0f); // right triangle - m_verts.emplace_back(m_dist + m_height, -(m_base / 2.0f) * m_a); - m_verts.emplace_back(m_dist + m_height, (m_base / 2.0f) * m_a); - } - else - { - m_verts.emplace_back(-m_squareSize / 2.0f, -m_squareSize / 2.0f * m_a); - m_verts.emplace_back(m_squareSize / 2.0f, -m_squareSize / 2.0f * m_a); - m_verts.emplace_back(m_squareSize / 2.0f, m_squareSize / 2.0f * m_a); - m_verts.emplace_back(-m_squareSize / 2.0f, -m_squareSize / 2.0f * m_a); - m_verts.emplace_back(m_squareSize / 2.0f, m_squareSize / 2.0f * m_a); - m_verts.emplace_back(-m_squareSize / 2.0f, m_squareSize / 2.0f * m_a); - } - - m_vertexShader = R"glsl( - - #version 410 core - - uniform mat4 mvp; - layout(location = 0) in vec3 inVertices; - layout(location = 1) in vec2 vertexUV; - out vec2 UV; - - void main(void) - { - gl_Position = mvp * vec4(inVertices,1.0); - UV = vertexUV; - } - )glsl"; - - m_fragmentShader = R"glsl( - - #version 410 core - - uniform vec4 colour; - uniform sampler2D CrosshairTexture; - uniform bool isBitmap; - out vec4 fragColour; - in vec2 UV; - - void main(void) - { - if (!isBitmap) - fragColour = colour; - else - fragColour = colour * texture(CrosshairTexture, UV); - } - )glsl"; - - m_shader.LoadShaders(m_vertexShader, m_fragmentShader); - m_shader.GetUniformLocationMap("mvp"); - m_shader.GetUniformLocationMap("CrosshairTexture"); - m_shader.GetUniformLocationMap("colour"); - m_shader.GetUniformLocationMap("isBitmap"); - - m_vbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(BasicVertex) * (MaxVerts)); + // update vbo mem m_vbo.Bind(true); - m_textvbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(UVCoords) * (int)m_uvCoord.size()); - m_textvbo.Bind(true); + m_vbo.BufferSubData(0, count * sizeof(BasicVertex), m_verts.data()); + } + else + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_crosshairTexId[player]); - glGenVertexArrays(1, &m_vao); - glBindVertexArray(m_vao); + m_textureCoordsCount = (int)m_uvCoord.size(); + matrix.Scale(m_dpiMultiplicator * m_scaleBitmap, m_dpiMultiplicator * m_scaleBitmap, 0); + + // update uniform memory + glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, matrix); + glUniform1i(m_shader.uniformLocMap["CrosshairTexture"], 0); // 0 or 1 or GL_TEXTURE0 GL_TEXTURE1 + glUniform4f(m_shader.uniformLocMap["colour"], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(m_shader.uniformLocMap["isBitmap"], true); + + // update vbo mem m_vbo.Bind(true); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(BasicVertex), 0); + m_vbo.BufferSubData(0, count * sizeof(BasicVertex), m_verts.data()); m_vbo.Bind(false); - m_textvbo.Bind(true); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(UVCoords), 0); + m_textvbo.BufferSubData(0, m_textureCoordsCount * sizeof(UVCoords), m_uvCoord.data()); m_textvbo.Bind(false); + } - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); + glBindVertexArray(m_vao); + glDrawArrays(GL_TRIANGLES, 0, count); + glBindVertexArray(0); - glBindVertexArray(0); - - return OKAY; + m_shader.DisableShader(); } -void CCrosshair::DrawCrosshair(New3D::Mat4 matrix, float x, float y, int player) +void CCrosshair::Update(uint32_t currentInputs, CInputs* Inputs, unsigned int xOffset, unsigned int yOffset, unsigned int xRes, unsigned int yRes) { - float r=0.0f, g=0.0f, b=0.0f; - int count = (int)m_verts.size(); + bool offscreenTrigger[2]{false}; + float x[2]{ 0.0f }, y[2]{ 0.0f }; - if (count > MaxVerts) { - count = MaxVerts; // maybe we could error out somehow - } + // Crosshairs can be enabled/disabled at run-tim + unsigned crosshairs = m_config["Crosshairs"].ValueAs(); + crosshairs &= 3; + if (!crosshairs) + return; - m_shader.EnableShader(); - matrix.Translate(x, y, 0); + // Set up the viewport and orthogonal projection + glUseProgram(0); // no shaders + glViewport(xOffset, yOffset, xRes, yRes); + glDisable(GL_DEPTH_TEST); // no Z-buffering needed - if (!m_isBitmapCrosshair) - { - switch (player) - { - case 0: // P1 red color - r = 1.0f; - g = 0.0f; - b = 0.0f; - break; - case 1: // P2 green color - r = 0.0f; - g = 1.0f; - b = 0.0f; - break; - } + if (!m_isBitmapCrosshair) + { + glDisable(GL_BLEND); // no blending + } + else + { + glEnable(GL_TEXTURE_2D); // enable texture mapping, blending and alpha chanel + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - matrix.Scale(m_dpiMultiplicator, m_dpiMultiplicator, 0); + New3D::Mat4 m; + m.Ortho(0.0, 1.0, 1.0, 0.0, -1.0f, 1.0f); - // update uniform memory - glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, matrix); - glUniform4f(m_shader.uniformLocMap["colour"], r, g, b, 1.0f); - glUniform1i(m_shader.uniformLocMap["isBitmap"], false); + // Convert gun coordinates to viewspace coordinates + if (currentInputs & Game::INPUT_ANALOG_GUN1) + { + x[0] = ((float)Inputs->analogGunX[0]->value / 255.0f); + y[0] = ((255.0f - (float)Inputs->analogGunY[0]->value) / 255.0f); + offscreenTrigger[0] = Inputs->analogTriggerLeft[0]->value || Inputs->analogTriggerRight[0]->value; + } + else if (currentInputs & Game::INPUT_GUN1) + { + x[0] = (float)Inputs->gunX[0]->value; + y[0] = (float)Inputs->gunY[0]->value; + GunToViewCoords(&x[0], &y[0]); + offscreenTrigger[0] = (Inputs->trigger[0]->offscreenValue) > 0; + } + if (currentInputs & Game::INPUT_ANALOG_GUN2) + { + x[1] = ((float)Inputs->analogGunX[1]->value / 255.0f); + y[1] = ((255.0f - (float)Inputs->analogGunY[1]->value) / 255.0f); + offscreenTrigger[1] = Inputs->analogTriggerLeft[1]->value || Inputs->analogTriggerRight[1]->value; + } + else if (currentInputs & Game::INPUT_GUN2) + { + x[1] = (float)Inputs->gunX[1]->value; + y[1] = (float)Inputs->gunY[1]->value; + GunToViewCoords(&x[1], &y[1]); + offscreenTrigger[1] = (Inputs->trigger[1]->offscreenValue) > 0; + } - // update vbo mem - m_vbo.Bind(true); - m_vbo.BufferSubData(0, count * sizeof(BasicVertex), m_verts.data()); - } - else - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_crosshairTexId[player]); + // Draw visible crosshairs - m_textureCoordsCount = (int)m_uvCoord.size(); + if ((crosshairs & 1) && !offscreenTrigger[0]) // Player 1 + { + DrawCrosshair(m, x[0], y[0], 0, xRes, yRes); + } + if ((crosshairs & 2) && !offscreenTrigger[1]) // Player 2 + { + DrawCrosshair(m, x[1], y[1], 1, xRes, yRes); + } - matrix.Scale(m_dpiMultiplicator * m_scaleBitmap, m_dpiMultiplicator * m_scaleBitmap, 0); - - // update uniform memory - glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, matrix); - glUniform1i(m_shader.uniformLocMap["CrosshairTexture"], 0); // 0 or 1 or GL_TEXTURE0 GL_TEXTURE1 - glUniform4f(m_shader.uniformLocMap["colour"], 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(m_shader.uniformLocMap["isBitmap"], true); - - // update vbo mem - m_vbo.Bind(true); - m_vbo.BufferSubData(0, count * sizeof(BasicVertex), m_verts.data()); - m_vbo.Bind(false); - m_textvbo.Bind(true); - m_textvbo.BufferSubData(0, m_textureCoordsCount * sizeof(UVCoords), m_uvCoord.data()); - m_textvbo.Bind(false); - } - - glBindVertexArray(m_vao); - glDrawArrays(GL_TRIANGLES, 0, count); - glBindVertexArray(0); - - m_shader.DisableShader(); -} - -void CCrosshair::Update(uint32_t currentInputs, CInputs* Inputs, unsigned int xOffset, unsigned int yOffset) -{ - bool offscreenTrigger[2]{false}; - float x[2]{ 0.0f }, y[2]{ 0.0f }; - - // Crosshairs can be enabled/disabled at run-tim - unsigned crosshairs = m_config["Crosshairs"].ValueAs(); - crosshairs &= 3; - if (!crosshairs) - return; - - // Set up the viewport and orthogonal projection - glUseProgram(0); // no shaders - glViewport(xOffset, yOffset, m_xRes, m_yRes); - glDisable(GL_DEPTH_TEST); // no Z-buffering needed - - if (!m_isBitmapCrosshair) - { - glDisable(GL_BLEND); // no blending - } - else - { - glEnable(GL_TEXTURE_2D); // enable texture mapping, blending and alpha chanel - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - New3D::Mat4 m; - m.Ortho(0.0, 1.0, 1.0, 0.0, -1.0f, 1.0f); - - // Convert gun coordinates to viewspace coordinates - if (currentInputs & Game::INPUT_ANALOG_GUN1) - { - x[0] = ((float)Inputs->analogGunX[0]->value / 255.0f); - y[0] = ((255.0f - (float)Inputs->analogGunY[0]->value) / 255.0f); - offscreenTrigger[0] = Inputs->analogTriggerLeft[0]->value || Inputs->analogTriggerRight[0]->value; - } - else if (currentInputs & Game::INPUT_GUN1) - { - x[0] = (float)Inputs->gunX[0]->value; - y[0] = (float)Inputs->gunY[0]->value; - GunToViewCoords(&x[0], &y[0]); - offscreenTrigger[0] = (Inputs->trigger[0]->offscreenValue) > 0; - } - if (currentInputs & Game::INPUT_ANALOG_GUN2) - { - x[1] = ((float)Inputs->analogGunX[1]->value / 255.0f); - y[1] = ((255.0f - (float)Inputs->analogGunY[1]->value) / 255.0f); - offscreenTrigger[1] = Inputs->analogTriggerLeft[1]->value || Inputs->analogTriggerRight[1]->value; - } - else if (currentInputs & Game::INPUT_GUN2) - { - x[1] = (float)Inputs->gunX[1]->value; - y[1] = (float)Inputs->gunY[1]->value; - GunToViewCoords(&x[1], &y[1]); - offscreenTrigger[1] = (Inputs->trigger[1]->offscreenValue) > 0; - } - - // Draw visible crosshairs - - if ((crosshairs & 1) && !offscreenTrigger[0]) // Player 1 - { - DrawCrosshair(m, x[0], y[0], 0); - } - if ((crosshairs & 2) && !offscreenTrigger[1]) // Player 2 - { - DrawCrosshair(m, x[1], y[1], 1); - } - - //PrintGLError(glGetError()); + //PrintGLError(glGetError()); } void CCrosshair::GunToViewCoords(float* x, float* y) { - *x = (*x - 150.0f) / (651.0f - 150.0f); // Scale [150,651] -> [0.0,1.0] - *y = (*y - 80.0f) / (465.0f - 80.0f); // Scale [80,465] -> [0.0,1.0] + *x = (*x - 150.0f) / (651.0f - 150.0f); // Scale [150,651] -> [0.0,1.0] + *y = (*y - 80.0f) / (465.0f - 80.0f); // Scale [80,465] -> [0.0,1.0] } -CCrosshair::CCrosshair(const Util::Config::Node& config) : m_config(config),m_xRes(0),m_yRes(0) +CCrosshair::CCrosshair(const Util::Config::Node& config) + : m_config(config), + m_vertexShader(nullptr), + m_fragmentShader(nullptr) { - m_vertexShader = nullptr; - m_fragmentShader = nullptr; } CCrosshair::~CCrosshair() diff --git a/Src/OSD/SDL/Crosshair.h b/Src/OSD/SDL/Crosshair.h index 66cbf9d..0bb1fd0 100644 --- a/Src/OSD/SDL/Crosshair.h +++ b/Src/OSD/SDL/Crosshair.h @@ -1,7 +1,7 @@ /** ** Supermodel ** A Sega Model 3 Arcade Emulator. - ** Copyright 2003-2022 The Supermodel Team + ** Copyright 2003-2023 The Supermodel Team ** ** This file is part of Supermodel. ** @@ -29,56 +29,54 @@ class CCrosshair { private: - const Util::Config::Node& m_config; - bool m_isBitmapCrosshair = false; - std::string m_crosshairStyle = ""; - GLuint m_crosshairTexId[2] = { 0 }; - int m_p1CrosshairW = 0, m_p1CrosshairH = 0, m_p2CrosshairW = 0, m_p2CrosshairH = 0; - float m_diagDpi = 0.0f, m_hDpi = 0.0f, m_vDpi = 0.0f; - unsigned int m_xRes=0; - unsigned int m_yRes=0; - const float m_base = 0.01f, m_height = 0.02f; // geometric parameters of each triangle - const float m_dist = 0.004f; // distance of triangle tip from center - float m_a = 0.0f; // aspect ratio (to square the crosshair) - const float m_squareSize = 1.0f; - const float m_standardDpi = 96.0f; // normal dpi for usual monitor (full hd) - float m_dpiMultiplicator = 0.0f; - const float m_scaleBitmap = 0.1f; + const Util::Config::Node& m_config; + bool m_isBitmapCrosshair = false; + std::string m_crosshairStyle = ""; + GLuint m_crosshairTexId[2] = { 0 }; + int m_p1CrosshairW = 0, m_p1CrosshairH = 0, m_p2CrosshairW = 0, m_p2CrosshairH = 0; + float m_diagDpi = 0.0f, m_hDpi = 0.0f, m_vDpi = 0.0f; + const float m_base = 0.01f, m_height = 0.02f; // geometric parameters of each triangle + const float m_dist = 0.004f; // distance of triangle tip from center + const float m_squareSize = 1.0f; + const float m_standardDpi = 96.0f; // normal dpi for usual monitor (full hd) + float m_dpiMultiplicator = 0.0f; + const float m_scaleBitmap = 0.1f; - struct BasicVertex - { - BasicVertex(float x, float y, float z) : x(x), y(y), z(z) {} - BasicVertex(float x, float y) : x(x), y(y), z(0.0f) {} - float x, y, z; - }; + struct BasicVertex + { + BasicVertex(float x, float y, float z) : x(x), y(y), z(z) {} + BasicVertex(float x, float y) : x(x), y(y), z(0.0f) {} + float x, y, z; + }; - struct UVCoords - { - UVCoords(float x, float y) : x(x), y(y) {} - float x, y; - }; + struct UVCoords + { + UVCoords(float x, float y) : x(x), y(y) {} + float x, y; + }; - std::vector m_verts; - std::vector m_uvCoord; + std::vector m_verts; + std::vector m_uvCoord; - GLSLShader m_shader; - VBO m_vbo; - VBO m_textvbo; - GLuint m_vao = 0; - int m_textureCoordsCount = 0; - const char* m_vertexShader; - const char* m_fragmentShader; + GLSLShader m_shader; + VBO m_vbo; + VBO m_textvbo; + GLuint m_vao = 0; + int m_textureCoordsCount = 0; + const char* m_vertexShader; + const char* m_fragmentShader; - const int MaxVerts = 1024; // per draw call + const int MaxVerts = 1024; // per draw call - void DrawCrosshair(New3D::Mat4 matrix, float x, float y, int player); - void GunToViewCoords(float* x, float* y); + void BuildCrosshairVertices(unsigned int xRes, unsigned int yRes); + void DrawCrosshair(New3D::Mat4 matrix, float x, float y, int player, unsigned int xRes, unsigned int yRes); + void GunToViewCoords(float* x, float* y); public: - CCrosshair(const Util::Config::Node& config); - ~CCrosshair(); - bool Init(); - void Update(uint32_t currentInputs, CInputs* Inputs, unsigned int, unsigned int); + CCrosshair(const Util::Config::Node& config); + ~CCrosshair(); + bool Init(); + void Update(uint32_t currentInputs, CInputs* Inputs, unsigned int xOffset, unsigned int yOffset, unsigned int xRes, unsigned int yRes); }; #endif diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index 9b8e899..d9b3c32 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -1,7 +1,7 @@ /** ** Supermodel ** A Sega Model 3 Arcade Emulator. - ** Copyright 2003-2022 The Supermodel Team + ** Copyright 2003-2023 The Supermodel Team ** ** This file is part of Supermodel. ** @@ -815,7 +815,7 @@ void EndFrameVideo() { // Show crosshairs for light gun games if (videoInputs) - s_crosshair->Update(currentInputs, videoInputs, xOffset, yOffset); + s_crosshair->Update(currentInputs, videoInputs, xOffset, yOffset, xRes, yRes); // Swap the buffers SDL_GL_SwapWindow(s_window); @@ -1515,7 +1515,7 @@ static Util::Config::Node DefaultConfig() static void Title(void) { puts("Supermodel: A Sega Model 3 Arcade Emulator (Version " SUPERMODEL_VERSION ")"); - puts("Copyright 2003-2022 by The Supermodel Team"); + puts("Copyright 2003-2023 by The Supermodel Team"); } static void Help(void)