From: Alexander Schmidt Date: Wed, 20 Jul 2016 20:29:48 +0000 (+0200) Subject: Changed directory structure X-Git-Url: http://git.treefish.org/~alex/seamulator.git/commitdiff_plain/40fe15ee6190427f3bbc5db4ff640442626cc3bb Changed directory structure --- diff --git a/CMakeLists.txt b/CMakeLists.txt index b6b7e6b..5fff49e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,20 +2,4 @@ cmake_minimum_required(VERSION 2.8) project(seamulator) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") - -find_package(OpenGL REQUIRED) -find_package(GLUT REQUIRED) -find_package(fftw3 REQUIRED) - -include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} - ${FFTW_INCLUDES}) - -add_executable(seamulator seamulator.cpp - sea.cpp watersurface.cpp surfacepoint.cpp - seaview.cpp) - -target_link_libraries(seamulator ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} - ${FFTW_LIBRARIES}) +add_subdirectory(src) diff --git a/include/sea.h b/include/sea.h new file mode 100644 index 0000000..798b92d --- /dev/null +++ b/include/sea.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + +#include + +#include "seafwd.h" + +#include "watersurfacefwd.h" + +class Sea +{ + public: + Sea(WaterSurfacePtr surface); + ~Sea(); + Sea(const Sea&) = delete; + Sea& operator=(const Sea&) = delete; + void update(); + + private: + static const double PHILLIPS_CONSTANT; + static const double GRAVITATIONAL_CONSTANT; + + WaterSurfacePtr m_surface; + double m_windDirection[2]; + double m_windSpeed; + std::random_device m_randomDevice; + std::mt19937 m_randomGenerator; + std::normal_distribution<> m_normalDistribution; + std::vector> m_fourierAmplitudes; + fftw_complex *m_fftwIn, *m_fftwOut; + fftw_plan m_fftwPlan; + std::chrono::time_point m_startTime; + + double phillipsSpectrum(double k_x, double k_y) const; + std::complex& fourierAmplitudeAt(int n, int m); + void generateFourierAmplitudes(); + double spatialFrequencyForIndex(int n) const; + double getRuntime() const; +}; diff --git a/include/seafwd.h b/include/seafwd.h new file mode 100644 index 0000000..22977d7 --- /dev/null +++ b/include/seafwd.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +class Sea; +using SeaPtr = std::shared_ptr; diff --git a/include/seaview.h b/include/seaview.h new file mode 100644 index 0000000..213bce0 --- /dev/null +++ b/include/seaview.h @@ -0,0 +1,20 @@ +#pragma once + +class SeaView +{ + public: + SeaView(double distance, double azimuth, double altitude); + void onMouseEvent(int button, int state, int x, int y); + void onMouseMove(int x, int y); + void setupView() const; + + private: + static constexpr double DISTANCE_MULTIPLIER = 0.1f; + + double m_distance; + double m_azimuth; + double m_altitude; + int m_mouseDownPos[2]; + double m_mouseDownAltitude; + double m_mouseDownAzimuth; +}; diff --git a/include/surfacepoint.h b/include/surfacepoint.h new file mode 100644 index 0000000..9a577f9 --- /dev/null +++ b/include/surfacepoint.h @@ -0,0 +1,11 @@ +#pragma once + +class SurfacePoint +{ + public: + double getHeight() const; + void setHeight(double height); + + private: + double m_height = 0; +}; diff --git a/include/watersurface.h b/include/watersurface.h new file mode 100644 index 0000000..22d3c48 --- /dev/null +++ b/include/watersurface.h @@ -0,0 +1,24 @@ +#pragma once + +#include "watersurfacefwd.h" + +#include + +#include "surfacepoint.h" + +class WaterSurface +{ + public: + WaterSurface(int size, double unitLength); + SurfacePoint& at(int x, int y); + const SurfacePoint& at(int x, int y) const; + int size() const; + double extend() const; + void draw() const; + void drawSingleTile(int x, int y) const; + + private: + std::vector m_points; + int m_size; + double m_extend; +}; diff --git a/include/watersurfacefwd.h b/include/watersurfacefwd.h new file mode 100644 index 0000000..efb7fe3 --- /dev/null +++ b/include/watersurfacefwd.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +class WaterSurface; +using WaterSurfacePtr = std::shared_ptr; diff --git a/sea.cpp b/sea.cpp deleted file mode 100644 index 85191d4..0000000 --- a/sea.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "sea.h" - -#include -#include -#include - -#include "watersurface.h" - -const double Sea::PHILLIPS_CONSTANT{0.0000001}; -const double Sea::GRAVITATIONAL_CONSTANT{9.8}; - -Sea::Sea(WaterSurfacePtr surface) : - m_surface{surface}, - m_windDirection{1, 0}, - m_windSpeed{10}, - m_randomGenerator{m_randomDevice()}, - m_normalDistribution{0.0, 1.0} -{ - m_fourierAmplitudes.resize(pow(m_surface->size() + 1, 2)); - generateFourierAmplitudes(); - - m_fftwIn = (fftw_complex*) - fftw_malloc(sizeof(fftw_complex) * pow(m_surface->size(), 2)); - m_fftwOut = (fftw_complex*) - fftw_malloc(sizeof(fftw_complex) * pow(m_surface->size(), 2)); - m_fftwPlan = fftw_plan_dft_2d - (m_surface->size(), m_surface->size(), m_fftwIn, m_fftwOut, - FFTW_BACKWARD, FFTW_MEASURE); - - m_startTime = std::chrono::system_clock::now(); -} - -Sea::~Sea() -{ - fftw_destroy_plan(m_fftwPlan); - fftw_free(m_fftwIn); fftw_free(m_fftwOut); -} - -double Sea::getRuntime() const -{ - auto timeNow = std::chrono::system_clock::now(); - auto durationMs = - std::chrono::duration_cast(timeNow - m_startTime); - - return durationMs.count() / 1000.0; -} - -void Sea::update() -{ - using namespace std::complex_literals; - - const double runtime = getRuntime(); - - for (int m = -m_surface->size()/2; m < m_surface->size()/2; ++m) { - const int positiveM = (m + m_surface->size()) % m_surface->size(); - - for (int n = -m_surface->size()/2; n < m_surface->size()/2; ++n) { - const double k = sqrt(pow(spatialFrequencyForIndex(n), 2) + - pow(spatialFrequencyForIndex(m), 2)); - const double omega = sqrt(GRAVITATIONAL_CONSTANT * k); - - std::complex amplitude = - fourierAmplitudeAt(n, m) * exp(1i * omega * runtime) + - std::conj(fourierAmplitudeAt(-n, -m)) * exp(-1i * omega * runtime); - - const int positiveN = (n + m_surface->size()) % m_surface->size(); - int fftwIndex = positiveM + positiveN * m_surface->size(); - - m_fftwIn[fftwIndex][0] = std::real(amplitude); - m_fftwIn[fftwIndex][1] = std::imag(amplitude); - } - } - - fftw_execute(m_fftwPlan); - - for (int y = 0; y < m_surface->size(); ++y) { - for (int x = 0; x < m_surface->size(); ++x) { - m_surface->at(x, y) - .setHeight(m_fftwOut[y + x * m_surface->size()][0]); - } - } -} - -double Sea::phillipsSpectrum(double k_x, double k_y) const -{ - const double k = sqrt(pow(k_x, 2) + pow(k_y, 2)); - const double L = pow(m_windSpeed, 2) / GRAVITATIONAL_CONSTANT; - - const double cosineFactor = pow((k_x / k) * m_windDirection[0] + - (k_y / k) * m_windDirection[1], 2); - - return PHILLIPS_CONSTANT * exp(-1 / pow(k * L, 2)) / pow(k, 4) * - cosineFactor; -} - -std::complex& Sea::fourierAmplitudeAt(int n, int m) -{ - return m_fourierAmplitudes.at - (n + m_surface->size()/2 + - (m + m_surface->size()/2) * m_surface->size()); -} - -double Sea::spatialFrequencyForIndex(int n) const -{ - return 2 * M_PI * n / m_surface->size(); -} - -void Sea::generateFourierAmplitudes() -{ - for (int m = -m_surface->size()/2; m < m_surface->size()/2; ++m) { - const double k_y = spatialFrequencyForIndex(m); - - for (int n = -m_surface->size()/2; n < m_surface->size()/2; ++n) { - const double k_x = spatialFrequencyForIndex(n); - - std::complex cDist(m_normalDistribution(m_randomGenerator), - m_normalDistribution(m_randomGenerator)); - - fourierAmplitudeAt(n, m) = - cDist * sqrt(phillipsSpectrum(k_x, k_y)) / sqrt(2); - } - } - - for (int n = -m_surface->size()/2; n < m_surface->size()/2; ++n) { - fourierAmplitudeAt(n, m_surface->size()/2) = - fourierAmplitudeAt(n, -m_surface->size()/2); - } - - for (int m = -m_surface->size()/2; m < m_surface->size()/2; ++m) { - fourierAmplitudeAt(m_surface->size()/2, m) = - fourierAmplitudeAt(-m_surface->size()/2, m); - } - - fourierAmplitudeAt(0, 0) = {0, 0}; -} diff --git a/sea.h b/sea.h deleted file mode 100644 index 798b92d..0000000 --- a/sea.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include "seafwd.h" - -#include "watersurfacefwd.h" - -class Sea -{ - public: - Sea(WaterSurfacePtr surface); - ~Sea(); - Sea(const Sea&) = delete; - Sea& operator=(const Sea&) = delete; - void update(); - - private: - static const double PHILLIPS_CONSTANT; - static const double GRAVITATIONAL_CONSTANT; - - WaterSurfacePtr m_surface; - double m_windDirection[2]; - double m_windSpeed; - std::random_device m_randomDevice; - std::mt19937 m_randomGenerator; - std::normal_distribution<> m_normalDistribution; - std::vector> m_fourierAmplitudes; - fftw_complex *m_fftwIn, *m_fftwOut; - fftw_plan m_fftwPlan; - std::chrono::time_point m_startTime; - - double phillipsSpectrum(double k_x, double k_y) const; - std::complex& fourierAmplitudeAt(int n, int m); - void generateFourierAmplitudes(); - double spatialFrequencyForIndex(int n) const; - double getRuntime() const; -}; diff --git a/seafwd.h b/seafwd.h deleted file mode 100644 index 22977d7..0000000 --- a/seafwd.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -class Sea; -using SeaPtr = std::shared_ptr; diff --git a/seamulator.cpp b/seamulator.cpp deleted file mode 100644 index c5f7936..0000000 --- a/seamulator.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include - -#include - -#include "sea.h" -#include "seaview.h" -#include "watersurface.h" - -const int LATTICE_SIZE{128}; -const double LATTICE_EXTEND{10}; -const int INIT_WINDOW_POS_X{50}; -const int INIT_WINDOW_POS_Y{50}; -const int INIT_WINDOW_WIDTH{800}; -const int INIT_WINDOW_HEIGHT{600}; -const double INIT_VIEW_DISTANCE{LATTICE_EXTEND * 1.5}; -const double INIT_VIEW_AZIMUTH{0}; -const double INIT_VIEW_ALTITUDE{M_PI / 4}; -const char WINDOW_TITLE[]{"seamulator"}; - -SeaPtr sea; -WaterSurfacePtr surface; -std::unique_ptr seaView; - -void glDisplayFunc(); -void glReshapeFunc(int width, int height); -void glMouseFunc(int button, int state, int x, int y); -void glMotionFunc(int x, int y); - -int main(int argc, char** argv) -{ - std::srand(std::time(0)); - - surface = std::make_shared(LATTICE_SIZE, LATTICE_EXTEND); - sea = std::make_shared(surface); - seaView = std::make_unique(INIT_VIEW_DISTANCE, INIT_VIEW_AZIMUTH, - INIT_VIEW_ALTITUDE); - - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_DOUBLE); - glutInitWindowSize(INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT); - glutInitWindowPosition(INIT_WINDOW_POS_X, INIT_WINDOW_POS_Y); - glutCreateWindow(WINDOW_TITLE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - glutDisplayFunc(glDisplayFunc); - glutReshapeFunc(glReshapeFunc); - glutMouseFunc(glMouseFunc); - glutMotionFunc(glMotionFunc); - - glutMainLoop(); - - return 0; -} - -void glDisplayFunc() -{ - glClear(GL_COLOR_BUFFER_BIT); - - seaView->setupView(); - sea->update(); - surface->draw(); - - glutSwapBuffers(); - glutPostRedisplay(); -} - -void glReshapeFunc(int width, int height) -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(50.0, ((float)width/(float)height), 0, 1000.0); - glViewport(0, 0, width, height); -} - -void glMouseFunc(int button, int state, int x, int y) -{ - seaView->onMouseEvent(button, state, x, y); -} - -void glMotionFunc(int x, int y) -{ - seaView->onMouseMove(x, y); -} diff --git a/seaview.cpp b/seaview.cpp deleted file mode 100644 index 035f557..0000000 --- a/seaview.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "seaview.h" - -#include - -#include - -SeaView::SeaView(double distance, double azimuth, double altitude) : - m_distance{distance}, - m_azimuth{azimuth}, - m_altitude{altitude} -{ -} - -void SeaView::onMouseEvent(int button, int state, int x, int y) -{ - if (button == 3 && state == 0) { - m_distance += m_distance*DISTANCE_MULTIPLIER; - glutPostRedisplay(); - } - else if (button == 4 && state == 0) { - m_distance -= m_distance*DISTANCE_MULTIPLIER; - glutPostRedisplay(); - } - else if (button == 0 && state == 0) { - m_mouseDownPos[0] = x; - m_mouseDownPos[1] = y; - m_mouseDownAzimuth = m_azimuth; - m_mouseDownAltitude = m_altitude; - } -} - -void SeaView::onMouseMove(int x, int y) -{ - m_altitude = - fmod(m_mouseDownAltitude + - (double)((y - m_mouseDownPos[1]) * - 2*M_PI / glutGet(GLUT_WINDOW_HEIGHT)), - (double)(2*M_PI)); - - m_azimuth = - fmod(m_mouseDownAzimuth + - (double)((x - m_mouseDownPos[0]) * - 2*M_PI / glutGet(GLUT_WINDOW_WIDTH)), - (double)(2*M_PI)); - - glutPostRedisplay(); -} - -void SeaView::setupView() const -{ - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - const double eyePos[3] = - {m_distance * cos(m_altitude) * sin(m_azimuth), - m_distance * cos(m_altitude) * cos(m_azimuth), - m_distance * sin(m_altitude)}; - - gluLookAt(eyePos[0], eyePos[1], eyePos[2], - 0, 0, 0, - 0, 0, 1); -} diff --git a/seaview.h b/seaview.h deleted file mode 100644 index 213bce0..0000000 --- a/seaview.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -class SeaView -{ - public: - SeaView(double distance, double azimuth, double altitude); - void onMouseEvent(int button, int state, int x, int y); - void onMouseMove(int x, int y); - void setupView() const; - - private: - static constexpr double DISTANCE_MULTIPLIER = 0.1f; - - double m_distance; - double m_azimuth; - double m_altitude; - int m_mouseDownPos[2]; - double m_mouseDownAltitude; - double m_mouseDownAzimuth; -}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..24c9ef6 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,18 @@ +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") + +find_package(OpenGL REQUIRED) +find_package(GLUT REQUIRED) +find_package(fftw3 REQUIRED) + +include_directories(${seamulator_SOURCE_DIR}/include + ${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} + ${FFTW_INCLUDES}) + +add_executable(seamulator seamulator.cpp + sea.cpp watersurface.cpp surfacepoint.cpp + seaview.cpp) + +target_link_libraries(seamulator ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} + ${FFTW_LIBRARIES}) diff --git a/src/sea.cpp b/src/sea.cpp new file mode 100644 index 0000000..85191d4 --- /dev/null +++ b/src/sea.cpp @@ -0,0 +1,135 @@ +#include "sea.h" + +#include +#include +#include + +#include "watersurface.h" + +const double Sea::PHILLIPS_CONSTANT{0.0000001}; +const double Sea::GRAVITATIONAL_CONSTANT{9.8}; + +Sea::Sea(WaterSurfacePtr surface) : + m_surface{surface}, + m_windDirection{1, 0}, + m_windSpeed{10}, + m_randomGenerator{m_randomDevice()}, + m_normalDistribution{0.0, 1.0} +{ + m_fourierAmplitudes.resize(pow(m_surface->size() + 1, 2)); + generateFourierAmplitudes(); + + m_fftwIn = (fftw_complex*) + fftw_malloc(sizeof(fftw_complex) * pow(m_surface->size(), 2)); + m_fftwOut = (fftw_complex*) + fftw_malloc(sizeof(fftw_complex) * pow(m_surface->size(), 2)); + m_fftwPlan = fftw_plan_dft_2d + (m_surface->size(), m_surface->size(), m_fftwIn, m_fftwOut, + FFTW_BACKWARD, FFTW_MEASURE); + + m_startTime = std::chrono::system_clock::now(); +} + +Sea::~Sea() +{ + fftw_destroy_plan(m_fftwPlan); + fftw_free(m_fftwIn); fftw_free(m_fftwOut); +} + +double Sea::getRuntime() const +{ + auto timeNow = std::chrono::system_clock::now(); + auto durationMs = + std::chrono::duration_cast(timeNow - m_startTime); + + return durationMs.count() / 1000.0; +} + +void Sea::update() +{ + using namespace std::complex_literals; + + const double runtime = getRuntime(); + + for (int m = -m_surface->size()/2; m < m_surface->size()/2; ++m) { + const int positiveM = (m + m_surface->size()) % m_surface->size(); + + for (int n = -m_surface->size()/2; n < m_surface->size()/2; ++n) { + const double k = sqrt(pow(spatialFrequencyForIndex(n), 2) + + pow(spatialFrequencyForIndex(m), 2)); + const double omega = sqrt(GRAVITATIONAL_CONSTANT * k); + + std::complex amplitude = + fourierAmplitudeAt(n, m) * exp(1i * omega * runtime) + + std::conj(fourierAmplitudeAt(-n, -m)) * exp(-1i * omega * runtime); + + const int positiveN = (n + m_surface->size()) % m_surface->size(); + int fftwIndex = positiveM + positiveN * m_surface->size(); + + m_fftwIn[fftwIndex][0] = std::real(amplitude); + m_fftwIn[fftwIndex][1] = std::imag(amplitude); + } + } + + fftw_execute(m_fftwPlan); + + for (int y = 0; y < m_surface->size(); ++y) { + for (int x = 0; x < m_surface->size(); ++x) { + m_surface->at(x, y) + .setHeight(m_fftwOut[y + x * m_surface->size()][0]); + } + } +} + +double Sea::phillipsSpectrum(double k_x, double k_y) const +{ + const double k = sqrt(pow(k_x, 2) + pow(k_y, 2)); + const double L = pow(m_windSpeed, 2) / GRAVITATIONAL_CONSTANT; + + const double cosineFactor = pow((k_x / k) * m_windDirection[0] + + (k_y / k) * m_windDirection[1], 2); + + return PHILLIPS_CONSTANT * exp(-1 / pow(k * L, 2)) / pow(k, 4) * + cosineFactor; +} + +std::complex& Sea::fourierAmplitudeAt(int n, int m) +{ + return m_fourierAmplitudes.at + (n + m_surface->size()/2 + + (m + m_surface->size()/2) * m_surface->size()); +} + +double Sea::spatialFrequencyForIndex(int n) const +{ + return 2 * M_PI * n / m_surface->size(); +} + +void Sea::generateFourierAmplitudes() +{ + for (int m = -m_surface->size()/2; m < m_surface->size()/2; ++m) { + const double k_y = spatialFrequencyForIndex(m); + + for (int n = -m_surface->size()/2; n < m_surface->size()/2; ++n) { + const double k_x = spatialFrequencyForIndex(n); + + std::complex cDist(m_normalDistribution(m_randomGenerator), + m_normalDistribution(m_randomGenerator)); + + fourierAmplitudeAt(n, m) = + cDist * sqrt(phillipsSpectrum(k_x, k_y)) / sqrt(2); + } + } + + for (int n = -m_surface->size()/2; n < m_surface->size()/2; ++n) { + fourierAmplitudeAt(n, m_surface->size()/2) = + fourierAmplitudeAt(n, -m_surface->size()/2); + } + + for (int m = -m_surface->size()/2; m < m_surface->size()/2; ++m) { + fourierAmplitudeAt(m_surface->size()/2, m) = + fourierAmplitudeAt(-m_surface->size()/2, m); + } + + fourierAmplitudeAt(0, 0) = {0, 0}; +} diff --git a/src/seamulator.cpp b/src/seamulator.cpp new file mode 100644 index 0000000..c5f7936 --- /dev/null +++ b/src/seamulator.cpp @@ -0,0 +1,85 @@ +#include +#include +#include + +#include + +#include "sea.h" +#include "seaview.h" +#include "watersurface.h" + +const int LATTICE_SIZE{128}; +const double LATTICE_EXTEND{10}; +const int INIT_WINDOW_POS_X{50}; +const int INIT_WINDOW_POS_Y{50}; +const int INIT_WINDOW_WIDTH{800}; +const int INIT_WINDOW_HEIGHT{600}; +const double INIT_VIEW_DISTANCE{LATTICE_EXTEND * 1.5}; +const double INIT_VIEW_AZIMUTH{0}; +const double INIT_VIEW_ALTITUDE{M_PI / 4}; +const char WINDOW_TITLE[]{"seamulator"}; + +SeaPtr sea; +WaterSurfacePtr surface; +std::unique_ptr seaView; + +void glDisplayFunc(); +void glReshapeFunc(int width, int height); +void glMouseFunc(int button, int state, int x, int y); +void glMotionFunc(int x, int y); + +int main(int argc, char** argv) +{ + std::srand(std::time(0)); + + surface = std::make_shared(LATTICE_SIZE, LATTICE_EXTEND); + sea = std::make_shared(surface); + seaView = std::make_unique(INIT_VIEW_DISTANCE, INIT_VIEW_AZIMUTH, + INIT_VIEW_ALTITUDE); + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE); + glutInitWindowSize(INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT); + glutInitWindowPosition(INIT_WINDOW_POS_X, INIT_WINDOW_POS_Y); + glutCreateWindow(WINDOW_TITLE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glutDisplayFunc(glDisplayFunc); + glutReshapeFunc(glReshapeFunc); + glutMouseFunc(glMouseFunc); + glutMotionFunc(glMotionFunc); + + glutMainLoop(); + + return 0; +} + +void glDisplayFunc() +{ + glClear(GL_COLOR_BUFFER_BIT); + + seaView->setupView(); + sea->update(); + surface->draw(); + + glutSwapBuffers(); + glutPostRedisplay(); +} + +void glReshapeFunc(int width, int height) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0, ((float)width/(float)height), 0, 1000.0); + glViewport(0, 0, width, height); +} + +void glMouseFunc(int button, int state, int x, int y) +{ + seaView->onMouseEvent(button, state, x, y); +} + +void glMotionFunc(int x, int y) +{ + seaView->onMouseMove(x, y); +} diff --git a/src/seaview.cpp b/src/seaview.cpp new file mode 100644 index 0000000..035f557 --- /dev/null +++ b/src/seaview.cpp @@ -0,0 +1,62 @@ +#include "seaview.h" + +#include + +#include + +SeaView::SeaView(double distance, double azimuth, double altitude) : + m_distance{distance}, + m_azimuth{azimuth}, + m_altitude{altitude} +{ +} + +void SeaView::onMouseEvent(int button, int state, int x, int y) +{ + if (button == 3 && state == 0) { + m_distance += m_distance*DISTANCE_MULTIPLIER; + glutPostRedisplay(); + } + else if (button == 4 && state == 0) { + m_distance -= m_distance*DISTANCE_MULTIPLIER; + glutPostRedisplay(); + } + else if (button == 0 && state == 0) { + m_mouseDownPos[0] = x; + m_mouseDownPos[1] = y; + m_mouseDownAzimuth = m_azimuth; + m_mouseDownAltitude = m_altitude; + } +} + +void SeaView::onMouseMove(int x, int y) +{ + m_altitude = + fmod(m_mouseDownAltitude + + (double)((y - m_mouseDownPos[1]) * + 2*M_PI / glutGet(GLUT_WINDOW_HEIGHT)), + (double)(2*M_PI)); + + m_azimuth = + fmod(m_mouseDownAzimuth + + (double)((x - m_mouseDownPos[0]) * + 2*M_PI / glutGet(GLUT_WINDOW_WIDTH)), + (double)(2*M_PI)); + + glutPostRedisplay(); +} + +void SeaView::setupView() const +{ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + const double eyePos[3] = + {m_distance * cos(m_altitude) * sin(m_azimuth), + m_distance * cos(m_altitude) * cos(m_azimuth), + m_distance * sin(m_altitude)}; + + gluLookAt(eyePos[0], eyePos[1], eyePos[2], + 0, 0, 0, + 0, 0, 1); +} diff --git a/src/surfacepoint.cpp b/src/surfacepoint.cpp new file mode 100644 index 0000000..4e39d07 --- /dev/null +++ b/src/surfacepoint.cpp @@ -0,0 +1,11 @@ +#include "surfacepoint.h" + +double SurfacePoint::getHeight() const +{ + return m_height; +} + +void SurfacePoint::setHeight(double height) +{ + m_height = height; +} diff --git a/src/watersurface.cpp b/src/watersurface.cpp new file mode 100644 index 0000000..a38ad57 --- /dev/null +++ b/src/watersurface.cpp @@ -0,0 +1,59 @@ +#include "watersurface.h" + +#include + +WaterSurface::WaterSurface(int size, double extend) : + m_size{size}, + m_extend{extend} +{ + m_points.resize(size*size); +} + +SurfacePoint& WaterSurface::at(int x, int y) +{ + return m_points.at(x + m_size*y); +} + +const SurfacePoint& WaterSurface::at(int x, int y) const +{ + return m_points.at(x + m_size*y); +} + +int WaterSurface::size() const +{ + return m_size; +} + +double WaterSurface::extend() const +{ + return m_extend; +} + +void WaterSurface::draw() const +{ + const double scaleFactor{m_extend / m_size}; + + glScalef(scaleFactor, scaleFactor, 1.0f); + glTranslatef(-(float)(m_size - 1) / 2, -(float)(m_size - 1) / 2, 0); + + for (int y = 0; y < m_size - 1; ++y) { + for (int x = 0; x < m_size - 1; ++x) { + drawSingleTile(x, y); + } + } +} + +void WaterSurface::drawSingleTile(int x, int y) const +{ + glBegin(GL_TRIANGLES); + + glVertex3f(x, y, at(x, y).getHeight()); + glVertex3f(x+1, y, at(x+1, y).getHeight()); + glVertex3f(x+1, y+1, at(x+1, y+1).getHeight()); + + glVertex3f(x, y, at(x, y).getHeight()); + glVertex3f(x, y+1, at(x, y+1).getHeight()); + glVertex3f(x+1, y+1, at(x+1, y+1).getHeight()); + + glEnd(); +} diff --git a/surfacepoint.cpp b/surfacepoint.cpp deleted file mode 100644 index 4e39d07..0000000 --- a/surfacepoint.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "surfacepoint.h" - -double SurfacePoint::getHeight() const -{ - return m_height; -} - -void SurfacePoint::setHeight(double height) -{ - m_height = height; -} diff --git a/surfacepoint.h b/surfacepoint.h deleted file mode 100644 index 9a577f9..0000000 --- a/surfacepoint.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -class SurfacePoint -{ - public: - double getHeight() const; - void setHeight(double height); - - private: - double m_height = 0; -}; diff --git a/watersurface.cpp b/watersurface.cpp deleted file mode 100644 index a38ad57..0000000 --- a/watersurface.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "watersurface.h" - -#include - -WaterSurface::WaterSurface(int size, double extend) : - m_size{size}, - m_extend{extend} -{ - m_points.resize(size*size); -} - -SurfacePoint& WaterSurface::at(int x, int y) -{ - return m_points.at(x + m_size*y); -} - -const SurfacePoint& WaterSurface::at(int x, int y) const -{ - return m_points.at(x + m_size*y); -} - -int WaterSurface::size() const -{ - return m_size; -} - -double WaterSurface::extend() const -{ - return m_extend; -} - -void WaterSurface::draw() const -{ - const double scaleFactor{m_extend / m_size}; - - glScalef(scaleFactor, scaleFactor, 1.0f); - glTranslatef(-(float)(m_size - 1) / 2, -(float)(m_size - 1) / 2, 0); - - for (int y = 0; y < m_size - 1; ++y) { - for (int x = 0; x < m_size - 1; ++x) { - drawSingleTile(x, y); - } - } -} - -void WaterSurface::drawSingleTile(int x, int y) const -{ - glBegin(GL_TRIANGLES); - - glVertex3f(x, y, at(x, y).getHeight()); - glVertex3f(x+1, y, at(x+1, y).getHeight()); - glVertex3f(x+1, y+1, at(x+1, y+1).getHeight()); - - glVertex3f(x, y, at(x, y).getHeight()); - glVertex3f(x, y+1, at(x, y+1).getHeight()); - glVertex3f(x+1, y+1, at(x+1, y+1).getHeight()); - - glEnd(); -} diff --git a/watersurface.h b/watersurface.h deleted file mode 100644 index 22d3c48..0000000 --- a/watersurface.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "watersurfacefwd.h" - -#include - -#include "surfacepoint.h" - -class WaterSurface -{ - public: - WaterSurface(int size, double unitLength); - SurfacePoint& at(int x, int y); - const SurfacePoint& at(int x, int y) const; - int size() const; - double extend() const; - void draw() const; - void drawSingleTile(int x, int y) const; - - private: - std::vector m_points; - int m_size; - double m_extend; -}; diff --git a/watersurfacefwd.h b/watersurfacefwd.h deleted file mode 100644 index efb7fe3..0000000 --- a/watersurfacefwd.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -class WaterSurface; -using WaterSurfacePtr = std::shared_ptr;