diff --git a/App/GameLayer.cpp b/App/GameLayer.cpp index bf95ba27c8c0c68da6f8362800189ae5c9af3311..5d548bdcd72176cf254a0b80931958cd8ab7950f 100644 --- a/App/GameLayer.cpp +++ b/App/GameLayer.cpp @@ -25,9 +25,8 @@ const QPong::Particle::Properties initialParticleSettings = { .size = 512, .position = {0.0, 0.0, 0.0}, .momentum = {0.0, 0.0, 0.0}, - .sharpness = 64.0, - .startValue = 0.01, - .hbar = 0.000125, + .dx = 6.475, + .hbar = 0.000175, .threads = 8 }; @@ -151,6 +150,7 @@ void QPong::GameLayer::onAttach() m_showPotentialsLocation = glGetUniformLocation(m_shader->getRendererID(), "u_showPotential"); m_isMomentumEnabled = glGetUniformLocation(m_shader->getRendererID(), "u_isMomentumEnabled"); reset(); + m_propagate = false; } void QPong::GameLayer::onDetach() @@ -180,11 +180,13 @@ void QPong::GameLayer::reset() m_properties.momentum.x = (1.0f - (2.0f * positive)) * (1.0 + static_cast<float>(xRand) / 120.0f) / 20.0; positive = rand() % 2; m_properties.momentum.y = (1.0f - (2.0f * positive)) * (1.0 + static_cast<float>(yRand) / 120.0f) / 20.0; + m_properties.position.y = m_properties.momentum.y * 5.0; } m_options.game = m_gaming; m_options.absorbtionEnabled = m_gaming; m_options.momentumEnabled = !m_gaming; + m_particle.reset(new Particle( m_properties, m_options, @@ -195,10 +197,11 @@ void QPong::GameLayer::reset() m_staticBorderPotential, m_dynamicPotential)); - m_restart = false; - m_gameCounts = true; constexpr double veryLittleInitialStep(0.00025); m_particle->update(veryLittleInitialStep); + m_gameCounts = true; + m_restart = false; + m_propagate = true; } void QPong::GameLayer::onUpdate(GuiCore::Timestep ts) @@ -278,23 +281,23 @@ void QPong::GameLayer::onGuiRender() { // GUI settings for the particle ImGui::Begin("Particle Settings"); - ImGui::DragFloat2("Start Position", glm::value_ptr(m_properties.position), 0.025f, -0.8f, 0.8f); + ImGui::DragFloat2("Start Position", glm::value_ptr(m_properties.position), 0.01f, -0.6f, 0.6f); // Select initial momentum for particle at restart ImGui::DragFloat2("Momentum [x,y]", glm::value_ptr(m_properties.momentum), 0.001f, -0.1f, 0.1f); ImGui::Checkbox("Random Momentum", &m_randomMomentum); - float sharpness = m_properties.sharpness; - if (ImGui::DragFloat("Sharpness", &sharpness, 5.0f, 5.0f, 1000.0f)) + float dx = static_cast<float>(m_properties.dx); + if (ImGui::DragFloat("dx", &dx, 0.1f, 2.0f, 50.0f)) { - m_properties.sharpness = sharpness; + m_properties.dx = static_cast<double>(dx); } // Select hbar, changes apply on the fly. - float hbar = m_properties.hbar; + float hbar = static_cast<float>(m_properties.hbar); if (ImGui::DragFloat("hbar", &hbar, 0.0000001f, 0.0000001f, 1.0f, "%.7f")) { - m_properties.hbar = hbar; + m_properties.hbar = static_cast<double>(hbar); } // This value increases or decreases the time step made every iteration. @@ -326,6 +329,7 @@ void QPong::GameLayer::onGuiRender() // Restart game if (ImGui::Button("Restart")) { + m_propagate = false; m_restart = true; } ImGui::Text("Player 1: %d", m_playerOne.getTotalScore()); @@ -347,6 +351,9 @@ void QPong::GameLayer::onGuiRender() m_options.absorbtionEnabled = false; m_options.momentumEnabled = true; m_restart = true; + m_properties.position.y = 0.4; + m_properties.momentum.y = 0.0; + m_properties.hbar *= 1.5; } ImGui::End(); } diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dbc4b4e2d365b7f4dfe34e8b7d0686491fbb7f3..fb68d1a993e7683a33a4884fe7453f3823c40ec5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(QPong VERSION 0.0.1 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_BUILD_TYPE Release) -list(APPEND basic_flags "-O3" "-Wextra" "-Wall" "-Wshadow" "-Wold-style-cast" "-pedantic" "-Wpedantic") +list(APPEND basic_flags "-O3" "-Wall" "-Wextra" "-Wshadow" "-Wold-style-cast" "-Werror" "-Wuninitialized" "-pedantic" "-Wpedantic") option(LOG_DEBUG_INFO "Enable logging t console" OFF) if(LOG_DEBUG_INFO) diff --git a/QPong/Bat.cpp b/QPong/Bat.cpp index da160c7ac4a46f129b6291b694bb382a9c77d54a..a090bc577ab13d0c5fab063e0b690bd2d126e234 100644 --- a/QPong/Bat.cpp +++ b/QPong/Bat.cpp @@ -27,18 +27,21 @@ QPong::Bat::Bat(double x, double y, int keyUp, int keyDown) void QPong::Bat::onUpdate(GuiCore::Timestep ts) { - constexpr double speed = 20.0; + constexpr double speed = 3.5; + constexpr double speedMultiplier = 1.05; if (GuiCore::Input::isKeyPressed(m_keyDown)) { - m_vy += s_speedStepSize * speed; + m_vy += s_speedStepSize * speed; + m_vy *= speedMultiplier; } else if (GuiCore::Input::isKeyPressed(m_keyUp)) { m_vy -= s_speedStepSize * speed; + m_vy *= speedMultiplier; } else { - m_vy = 0.0; + m_vy *= 0.85; } constexpr double maxSpeedFactor = 300.0; @@ -81,7 +84,8 @@ double QPong::Bat::getPotential(double x, double y) const { dist = pow2(m_x - x) + m_width; } - return 1.0 / (pow2(dist) ) * scale; + auto pot = 1.0 / (pow2(dist)) * scale; + return(pot); } double QPong::Bat::getX() const diff --git a/QPong/CMakeLists.txt b/QPong/CMakeLists.txt index 42f71f946245e575797fc3655ccdaaa1d6bbcf6a..0b8cad96dcc23810823c392292a07a4cb5a3ff15 100644 --- a/QPong/CMakeLists.txt +++ b/QPong/CMakeLists.txt @@ -21,12 +21,4 @@ target_link_libraries(QPong GuiCore fftw3 fftw3_omp - ) - -# target_include_directories( QPong -# PUBLIC -# . -# .. -# ../libs -# ../libs/imgui/examples/libs/gl3w -# ) \ No newline at end of file + ) \ No newline at end of file diff --git a/QPong/Particle.cpp b/QPong/Particle.cpp index ea20c6993ea4c8265480797b7adabed067ea180d..2c8d8a2eea918153da88eb0d6ea9c77d5a40dd84 100644 --- a/QPong/Particle.cpp +++ b/QPong/Particle.cpp @@ -61,17 +61,18 @@ Particle::Particle(Properties properties, GameOptions &options, Player &playerOn Log::get()->debug("Init Particle"); m_xAt = new double[m_properties.elements()]; m_yAt = new double[m_properties.elements()]; - m_E_At = new double[m_properties.elements()]; + m_P_At = new double[m_properties.elements()]; for (int i{0}; i < m_properties.elements(); ++i) { m_xAt[i] = xAtIndex(i, m_properties.size); m_yAt[i] = yAtIndex(i, m_properties.size); - m_E_At[i] = (pow2(pxAtIndex(i, m_properties.size, m_properties.hbar)) + pow2(pyAtIndex(i, m_properties.size, m_properties.hbar))) / (2.0 * 1.0); + m_P_At[i] = pow2(pxAtIndex(i, m_properties.size, m_properties.hbar)) + pow2(pyAtIndex(i, m_properties.size, m_properties.hbar)); } int memorySize = sizeof(fftw_complex) * m_properties.elements(); - m_psi = static_cast<std::complex<double> *>(fftw_malloc(memorySize)); + m_psi_positional = static_cast<std::complex<double> *>(fftw_malloc(memorySize)); + m_psi_momentum = static_cast<std::complex<double> *>(fftw_malloc(memorySize)); m_momentum = static_cast<std::complex<double> *>(fftw_malloc(memorySize)); initialiseParticleMomentum(); @@ -94,12 +95,18 @@ Particle::Particle(Properties properties, GameOptions &options, Player &playerOn m_planForward = fftw_plan_dft_2d( m_properties.size, m_properties.size, - reinterpret_cast<fftw_complex*>(m_psi), - reinterpret_cast<fftw_complex*>(m_psi), + reinterpret_cast<fftw_complex*>(m_psi_positional), + reinterpret_cast<fftw_complex*>(m_psi_momentum), FFTW_FORWARD, FFTW_MEASURE); fftw_plan_with_nthreads(m_properties.threads); - m_planBackwards = fftw_plan_dft_2d(m_properties.size, m_properties.size, reinterpret_cast<fftw_complex*>(m_psi), reinterpret_cast<fftw_complex*>(m_psi), FFTW_BACKWARD, FFTW_MEASURE); + m_planBackwards = fftw_plan_dft_2d( + m_properties.size, + m_properties.size, + reinterpret_cast<fftw_complex*>(m_psi_momentum), + reinterpret_cast<fftw_complex*>(m_psi_positional), + FFTW_BACKWARD, + FFTW_MEASURE); int numberOfThreads = m_properties.threads; for (int i = 0; i < numberOfThreads; i++) @@ -131,16 +138,17 @@ Particle::~Particle() } std::this_thread::sleep_for(std::chrono::milliseconds(500)); - fftw_free(m_psi); + fftw_free(m_psi_positional); + fftw_free(m_psi_momentum); delete (m_xAt); delete (m_yAt); - delete (m_E_At); + delete (m_P_At); delete (m_momentum); } std::complex<double> *Particle::getPsi() const { - return m_psi; + return m_psi_positional; } std::complex<double> *Particle::getMomentum() const @@ -155,40 +163,37 @@ int Particle::arrayElementCount() const void Particle::initialiseParticleMomentum() { - constexpr std::complex<double> ci{0.0, 1.0}; // complex number + constexpr std::complex<double> ci{0.0, 1.0}; const double hbar = m_properties.hbar; - const double A0 = m_properties.startValue; const double px0 = m_properties.momentum.x; const double py0 = m_properties.momentum.y; const double x0 = m_properties.position.x; const double y0 = m_properties.position.y; - const double lambda = m_properties.sharpness; + const double dx = m_properties.dx; double sum{0.0}; - double m_particleAbsoluteSumStart = 0.0; double y{0.0}; double x{0.0}; for (auto i{0}; i < arrayElementCount(); ++i) { x = m_xAt[i]; y = m_yAt[i]; - m_psi[i] = A0 * exp(ci / hbar * (x * px0 + y * py0) - lambda * (pow2(x - x0) + pow2(y - y0))); - sum += pow2(std::real(m_psi[i])) + pow2(std::imag(m_psi[i])); + m_psi_positional[i] = exp(ci / hbar * (x * px0 + y * py0) - pow2(dx) * (pow2(x-x0) + pow2(y-y0))); + sum += pow2(std::real(m_psi_positional[i])) + pow2(std::imag(m_psi_positional[i])); } for (auto i{0}; i < arrayElementCount(); ++i) { - m_psi[i] *= 10.0 / sqrt(sum); - m_particleAbsoluteSumStart += pow2(std::real(m_psi[i])) + pow2(std::imag(m_psi[i])); + m_psi_positional[i] *= 10.0 / sqrt(sum); } Log::get()->trace("Particle initialised"); } double Particle::absorbParticle(int i, double c) { - double normPrevious = pow2(std::real(m_psi[i])) + pow2(std::imag(m_psi[i])); - double absorb = pow2(std::cos(c * 10)); - m_psi[i] *= absorb; - double delta = normPrevious - (pow2(std::real(m_psi[i])) + pow2(std::imag(m_psi[i]))); + double normPrevious = pow2(std::real(m_psi_positional[i])) + pow2(std::imag(m_psi_positional[i])); + double absorb = pow2(std::cos(c * 10.0)); + m_psi_positional[i] *= absorb; + double delta = normPrevious - (pow2(std::real(m_psi_positional[i])) + pow2(std::imag(m_psi_positional[i]))); return delta; } @@ -198,39 +203,34 @@ void Particle::applyPotentials(int indexBegin, int indexEnd, double dt) const double hbar = m_properties.hbar; double x{0.0}; double y{0.0}; - const double potential = 1.0; double particleAbsorbtAtPlayerOne = 0.0; double particleAbsorbtAtPlayerTwo = 0.0; for (int i{indexBegin}; i < indexEnd; ++i) { - double potSum = 1.0; - if (m_options.potentialsEnabled) + double potSum = 0.0; + x = m_xAt[i]; + y = m_yAt[i]; + if (m_options.absorbtionEnabled) { - potSum = 0.0; - x = m_xAt[i]; - y = m_yAt[i]; - if (m_options.absorbtionEnabled) + if (x < m_leftBat.getX()) + { + double distanceToEdge = -m_leftBat.getX() + x; + double c = distanceToEdge * (M_PI / 2.0) / (1.0 + m_leftBat.getX()); + particleAbsorbtAtPlayerOne += absorbParticle(i, c); + } + if (x > m_rightBat.getX()) { - if (x < m_leftBat.getX()) - { - double distanceToEdge = -m_leftBat.getX() + x; - double c = distanceToEdge * (M_PI / 2.0) / (1.0 + m_leftBat.getX()); - particleAbsorbtAtPlayerOne += absorbParticle(i, c); - } - if (x > m_rightBat.getX()) - { - double distanceToEdge = x - m_rightBat.getX(); - double c = distanceToEdge * (M_PI / 2.0) / (1.0 + m_rightBat.getX()); - particleAbsorbtAtPlayerTwo += absorbParticle(i, c); - } + double distanceToEdge = x - m_rightBat.getX(); + double c = distanceToEdge * (M_PI / 2.0) / (1.0 + m_rightBat.getX()); + particleAbsorbtAtPlayerTwo += absorbParticle(i, c); } - double potLeftBat = m_leftBat.getPotential(x, y); - double potRightBat = m_rightBat.getPotential(x, y); - potSum = potLeftBat + potRightBat + m_staticBorders[i]; } - auto psi = m_psi[i] * exp(-ci * dt / hbar * potential * potSum); - m_psi[i] = psi; + double potLeftBat = m_leftBat.getPotential(x, y); + double potRightBat = m_rightBat.getPotential(x, y); + potSum = potLeftBat + potRightBat + m_staticBorders[i]; + auto psi = m_psi_positional[i] * exp(-ci * dt / hbar * potSum); + m_psi_positional[i] = psi; if (m_options.potentialsEnabled) { m_dynamicPotential[i] = potSum; @@ -247,7 +247,7 @@ void Particle::moveForward(int indexBegin, int indexEnd, double dt) const double N = 1.0 / static_cast<double>(arrayElementCount()); for (int i{indexBegin}; i < indexEnd; ++i) { - m_psi[i] *= exp(-ci * dt / hbar * m_E_At[i]) * N; + m_psi_momentum[i] *= exp(((-ci * dt) / (2.0 * hbar)) * m_P_At[i]) * N; } } @@ -279,7 +279,7 @@ void Particle::updateMomentumView(int indexBegin, int indexEnd) { x = x + halfArraySize; } - m_momentum[i] = m_psi[(y * m_properties.size) - x] * 100.0; + m_momentum[i] = m_psi_momentum[(y * m_properties.size) - x] * 100.0; } } diff --git a/QPong/Particle.hpp b/QPong/Particle.hpp index 41dfa3ca86f9ce127c17545632ba3c2095b1adea..23eb117dc4b329070264505954e7836cda84920b 100644 --- a/QPong/Particle.hpp +++ b/QPong/Particle.hpp @@ -34,8 +34,7 @@ namespace QPong int size; glm::vec3 position; glm::vec3 momentum; - double sharpness; - double startValue; + double dx; double hbar; int threads; int elements() const {return size * size;} @@ -86,10 +85,11 @@ namespace QPong fftw_plan m_planBackwards; double *m_xAt; double *m_yAt; - double *m_E_At; + double *m_P_At; float *m_staticBorders; float *m_dynamicPotential; - std::complex<double> *m_psi; + std::complex<double> *m_psi_positional; + std::complex<double> *m_psi_momentum; std::complex<double> *m_momentum; double m_timeFFT; }; diff --git a/QPong/Utils.cpp b/QPong/Utils.cpp index 4e0ae381cfb07507aecb67fe2ffe137198f25928..eac6ee2a853ff34e173cb3e5bb29a5a078c1913c 100644 --- a/QPong/Utils.cpp +++ b/QPong/Utils.cpp @@ -10,7 +10,7 @@ void calculatePointPositions(float *positions, int arraySize) constexpr float size{3.175f}; constexpr float xOffset{0.0f}; constexpr float yOffset{-0.175f}; - + constexpr float width{size}; constexpr float xMin{-width / 2.0}; constexpr float xMax{width / 2.0}; @@ -88,15 +88,12 @@ void calculateBorderPotential(float *potential, [[maybe_unused]] double *xAt, do void calculateMorseBox(float *potential, double *xAt, double *yAt, int arrayElements) { constexpr double grow = 0.1; - constexpr double scalePotential = 1.0; for (int i{0}; i < arrayElements; ++i) { auto x = xAt[i] * grow; auto y = yAt[i] * grow; auto d = sqrt(pow2(x) + pow2(y)); - // V(x) = 1 / cosh^2(x) = 1 / (1/2 * (cosh(2x)+1)) auto V = 1.0 / ( 0.5 * (cosh(2.0 * d) + 1.0)); - V *= scalePotential; potential[i] = 1.0 - V; } } @@ -118,29 +115,30 @@ void calculateGaussBox(float *potential, double *xAt, double *yAt, int arrayElem void calculateH2Box(float *potential, double *xAt, double *yAt, int arrayElements) { - constexpr double grow = 0.001; + constexpr double grow { 0.0018 }; + constexpr double reducedSingularity { 0.0991 }; + constexpr double scale { 0.10039 }; for (int i{0}; i < arrayElements; ++i) { auto x = xAt[i] * grow; auto y = yAt[i] * grow; - auto d = sqrt(pow2(x) + pow2(y)) + 0.1; - auto V = 0.10035 / d; + auto d = sqrt(pow2(x) + pow2(y)) + reducedSingularity; + auto V = scale / d; potential[i] = 1.0 - V; } } - -// void Kegel(float *potential, double *xAt, double *yAt, int arrayElements) -// { -// constexpr double grow = 1.0; -// constexpr double scalePotential = 0.005; -// for (int i{0}; i < arrayElements; ++i) -// { -// auto x = xAt[i] * grow; -// auto y = yAt[i] * grow; -// auto d = sqrt(pow2(x) + pow2(y)); -// auto V = d; -// V *= scalePotential; -// potential[i] = V; -// } -// } \ No newline at end of file +void Kegel(float *potential, double *xAt, double *yAt, int arrayElements) +{ + constexpr double grow = 1.0; + constexpr double scalePotential = 0.005; + for (int i{0}; i < arrayElements; ++i) + { + auto x = xAt[i] * grow; + auto y = yAt[i] * grow; + auto d = sqrt(pow2(x) + pow2(y)); + auto V = d; + V *= scalePotential; + potential[i] = V; + } +} diff --git a/QPong/Utils.hpp b/QPong/Utils.hpp index 53a305ef3b4864b7841dc6d0876d51a47d4383b5..155d7102f30eaf8e35730546df073b6f384e677c 100644 --- a/QPong/Utils.hpp +++ b/QPong/Utils.hpp @@ -20,4 +20,6 @@ void calculateBorderPotential(float *potential, double *xAt, double *yAt, int ar void calculateMorseBox(float *potential, double *xAt, double *yAt, int arrayElemnts); void calculateGaussBox(float *potential, double *xAt, double *yAt, int arrayElemnts); void calculateH2Box(float *potential, double *xAt, double *yAt, int arrayElemnts); -#endif \ No newline at end of file +void calculateKegelBox(float *potential, double *xAt, double *yAt, int arrayElemnts); + +#endif diff --git a/assets/shaders/particle.vert.glsl b/assets/shaders/particle.vert.glsl index 9cd55d644a685a005400088b67f21e38c9500765..6dc1b88b1c25b0c7d809fa916f6eaa34b6b5b92c 100644 --- a/assets/shaders/particle.vert.glsl +++ b/assets/shaders/particle.vert.glsl @@ -25,16 +25,16 @@ void main() gl_Position = u_viewProjection * vec4(pos, 1.0f); // Calculate "color" value of the momentum - float pot = potential * 100.0 * u_showPotential; + float pot = abs(potential * 100.0f * u_showPotential); // Generate color from data float real = v_particle_complex[0]; float imag = v_particle_complex[1]; float real2 = real * real; float imag2 = imag * imag; - + fragmentColor = vec3( - sqrt(real2) * 5.0 + pot, // red - (sqrt(real2) + sqrt(imag2)) * 5.0 + pot, // green - sqrt(imag2) * 5.0 + pot); // blue + pot + sqrt(real2) * 5.0f, + pot + (sqrt(real2) + sqrt(imag2)) * 5.0f, + pot + sqrt(imag2) * 5.0f); }