From 602d0bb3428762c8f9ec43f719871fb9ff7420f6 Mon Sep 17 00:00:00 2001 From: Andreas Ortmann Date: Tue, 4 Oct 2016 16:09:15 +0200 Subject: [PATCH] adding camera to 3d render. angles not yet working. --- data/shader/gameobjects.vert | 5 +- data/shader/particle.vert | 3 + game/CMakeLists.txt | 3 +- game/game.cpp | 1 + game/game_window.hpp | 5 +- game/renderer_polygon_3d/camera.cpp | 0 game/renderer_polygon_3d/camera.hpp | 110 ++++++++++++++++++ .../renderer_polygon_3d.cpp | 17 +-- .../renderer_polygon_3d.hpp | 10 +- game/state/state.cpp | 65 +++++++++-- game/state/state.hpp | 3 + test/shoot_n_times.py | 4 +- 12 files changed, 197 insertions(+), 29 deletions(-) create mode 100644 game/renderer_polygon_3d/camera.cpp create mode 100644 game/renderer_polygon_3d/camera.hpp diff --git a/data/shader/gameobjects.vert b/data/shader/gameobjects.vert index 91f5184..e47a6af 100644 --- a/data/shader/gameobjects.vert +++ b/data/shader/gameobjects.vert @@ -8,13 +8,16 @@ varying vec3 normal; varying vec3 lightDirection; uniform mat4 model; +uniform mat4 view; uniform vec3 lightPosition; uniform float aspectRatio; void main() { // TODO: this becomes invalid when projection matrices are used - vec3 p = (model*vec4(in_vertex/vec3(aspectRatio, 1.0, 1.0), 1.0)).xyz; + vec3 asp = vec3(aspectRatio, 1.0, 1.0); + //vec3 asp = vec3(1.0, 1.0, 1.0); + vec3 p = (view*model*vec4(in_vertex, 1.0)).xyz; lightDirection = normalize(lightPosition - p); vertex = p.xyz; diff --git a/data/shader/particle.vert b/data/shader/particle.vert index 30242f0..2f8266f 100644 --- a/data/shader/particle.vert +++ b/data/shader/particle.vert @@ -28,6 +28,8 @@ void main() //decay = max(decay*decay, sqrt(decay)); decay = ageMod / halfAge; + //vec3 av = vec3(aspectRatio, 1.0, 1.0); + // faster particles are smaller // TODO: scale by time too! scale down fast after 3 halfAges float scaleBySpeed = (1.0 - 0.95*length(in_velocity)/maxVelocity); @@ -39,6 +41,7 @@ void main() if (md > in_maxDist) { move *= in_maxDist / md; } + vec3 offset = move + in_position; p += offset; diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 0d249ac..9b10ec9 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -18,6 +18,7 @@ set(GAME_SRC renderer_polygon_2d/renderer_polygon_2d.cpp renderer_polygon_3d/renderer_polygon_3d.cpp + renderer_polygon_3d/camera.cpp renderer_polygon_3d/polygon_model.cpp renderer_polygon_3d/particle_batch.cpp renderer_polygon_3d/image_texture.cpp @@ -44,7 +45,7 @@ set(GAME_SRC set(SOUND_LIBRARIES "") - # TODO: make optional! +# TODO: make optional! #set(GAME_SRC ${GAME_SRC} sound/sound.cpp) #set(SOUND_LIBRARIES -lportaudio -lsndfile) set(GAME_SRC ${GAME_SRC} sound/dummy_sound.cpp) diff --git a/game/game.cpp b/game/game.cpp index c6c448a..1538e58 100644 --- a/game/game.cpp +++ b/game/game.cpp @@ -82,5 +82,6 @@ bool Game::cycle(float dt) } void Game::resize(int width, int height) { + std::cout<<"game resize to " << width << " X " << height << std::endl; m_state->setPlayingFieldSize(width, height); } diff --git a/game/game_window.hpp b/game/game_window.hpp index 3723bd4..c63ad75 100644 --- a/game/game_window.hpp +++ b/game/game_window.hpp @@ -47,16 +47,13 @@ class GameWindow : public endofthejedi::GLWindow { void resize() override { - std::cout<<"resize()" << std::endl; + //std::cout<<"resize()" << std::endl; glViewport(0, 0, getwidth(), getheight()); // resize the game m_game->resize(getwidth(), getheight()); - // TODO: mark it and let the reinit() happen in the next so it happnens just once. while doing the resize - m_game->state()->init(); - // resize the renderer m_renderer.setWindowSize(getwidth(), getheight()); } diff --git a/game/renderer_polygon_3d/camera.cpp b/game/renderer_polygon_3d/camera.cpp new file mode 100644 index 0000000..e69de29 diff --git a/game/renderer_polygon_3d/camera.hpp b/game/renderer_polygon_3d/camera.hpp new file mode 100644 index 0000000..565de84 --- /dev/null +++ b/game/renderer_polygon_3d/camera.hpp @@ -0,0 +1,110 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace endofthejedi { + // TODO: + // add shaking attributes to camera too + // and dirt effects + + class Camera { + public: + Camera() : m_aspectRatio(1.0), m_zoom(1.0), m_position(0.0, 0.0, 0.0), m_angles(0.0, 0.0, 0.0), m_dirty(true) + { + } + + // set camera zoom: + // 0 makes no sense, + // << 1 scales down + // 1 is neutral + // >> 1 makes things bigger + void setCameraZoom(float zoom) + { + if (zoom != m_zoom) { + m_zoom = zoom; + m_dirty = true; + } + } + + // position of the camera in world space + void setCameraPosition(const glm::vec3 &pos) + { + if (pos != m_position) { + m_position = pos; + m_dirty = true; + } + } + + // some angles (in rad) for the camera. + void setCameraAngles(const glm::vec3 &angles) + { + if (angles != m_angles) { + m_angles = angles; + m_dirty = true; + } + } + + // all three arguments. + void setCameraPositionAnglesZoom(const glm::vec3 &position, const glm::vec3 &angles, float zoom) + { + setCameraZoom(zoom); + setCameraPosition(position); + setCameraAngles(angles); + } + + float zoom() const { return m_zoom; } + const glm::vec3 &position() const { return m_position; } + const glm::vec3 &angles() const { return m_angles; } + + float aspectRatio() const { return m_aspectRatio; } + + void setAspectRatio(float r) + { + if (r != m_aspectRatio) { + m_aspectRatio = r; + m_dirty = true; + } + } + + // recompute view matrix. return true if it was dirty and is now clean + // and recomputed. + bool refresh() + { + if (m_dirty) { + m_dirty = false; + recomputeMatrix(); + return true; + } + return false; + } + + const glm::mat4 &viewMatrix() const { return m_viewMatrix; } + + void recomputeMatrix() + { + glm::mat4 view; + + // TODO: rest is smissing + + //float a = 2.0*M_PI*m_lastTime/10.0; + //float s = glm::mod(m_lastTime, 5.0f)/1.0f; + view = glm::translate(view, m_position); + view = glm::scale(view, glm::vec3(m_zoom/m_aspectRatio, m_zoom, m_zoom)); + + m_viewMatrix = view; + } + + private: + float m_aspectRatio; + float m_zoom; + glm::vec3 m_position; + glm::vec3 m_angles; + bool m_dirty; + + glm::mat4 m_viewMatrix; +}; +} diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.cpp b/game/renderer_polygon_3d/renderer_polygon_3d.cpp index 08e34d4..d9670d2 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.cpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.cpp @@ -127,7 +127,7 @@ namespace endofthejedi { glClearColor(0.0, 0.0, 0.0, 1.0); - renderBackgroundImage(); + //renderBackgroundImage(); //float s = 0.1; //glClearColor(s, s, 1.2*s, 1.0); @@ -142,6 +142,12 @@ namespace endofthejedi { //std::cout<<"setting aspect ratio: " << m_aspectRatio << std::endl; glUniform1f(m_shader_game_objects.location("aspectRatio"), m_aspectRatio); + m_camera.refresh(); + auto *ptr = glm::value_ptr(m_camera.viewMatrix()); + + glUniformMatrix4fv(m_shader_game_objects.location("view"), 1, GL_FALSE, ptr); + glUniformMatrix4fv(m_shader_particles.location("view"), 1, GL_FALSE, ptr); + renderPlanets(); renderShips(); renderMissiles(); @@ -601,7 +607,7 @@ namespace endofthejedi { } } - glUniform1i( shader->location("explLightsNum"), numExplLights); + glUniform1i(shader->location("explLightsNum"), numExplLights); if (numExplLights != 0) { glUniform3fv(shader->location("explLightsPos"), numExplLights, glm::value_ptr(positions[0])); @@ -611,11 +617,6 @@ namespace endofthejedi { void RendererPolygon3d::setWindowSize(int px, int py) { - m_aspectRatio = (float) px / (float) py; - } - - void RendererPolygon3d::setCameraMatrix(const glm::mat4 &cam) - { - (void) cam; + m_camera.setAspectRatio((float) px / (float) py); } } diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.hpp b/game/renderer_polygon_3d/renderer_polygon_3d.hpp index cb53f5f..963cbeb 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.hpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.hpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -24,6 +23,7 @@ #include "particle_batch.hpp" #include "polygon_model.hpp" #include "image_texture.hpp" +#include "camera.hpp" namespace endofthejedi { @@ -33,7 +33,11 @@ namespace endofthejedi { void render(const game::State *state) override; void setWindowSize(int px, int py); - void setCameraMatrix(const glm::mat4 &cam); + //void setCameraMatrix(const glm::mat4 &cam); + + + // TODO: fov as argument? + Camera &camera(); private: void renderPlanets(); @@ -96,5 +100,7 @@ namespace endofthejedi { std::string m_backgroundTexturePath; ImageTexture *m_texture; + + Camera m_camera; }; } diff --git a/game/state/state.cpp b/game/state/state.cpp index af4a2f7..9c197bb 100644 --- a/game/state/state.cpp +++ b/game/state/state.cpp @@ -39,12 +39,56 @@ namespace game { m_defaultEnergy = 10.0; m_maxNumTraces = 10; - setPlayingFieldCenter(0, 0); + //setPlayingFieldCenter(0, 0); // TODO: need aspect ratio or data! //setPlayingFieldSize(1000, 300); - setupPlanets(numPlanets); + (void) numPlanets; + //setupPlanets(numPlanets); + + setupTestPlanets(); + + m_needReInit = false; + } + + void State::setupTestPlanets() + { + // XXX simple setup for testing + // TODO: spawn hmmm.m.... + //float aspectRatio = 1.0; + float aspectRatio = m_playingFieldSize.x / m_playingFieldSize.y; + (void) aspectRatio; + + float smallRadius = 0.05; + float sunRadius = 0.2; + + int n = 10.0; + float nf = n-1; + + std::cout<<"spawing planets..." << std::endl; + + // distribute planets in an area equal width the same aspect ratio as the screen + + planets.push_back(new Planet(generateId(), glm::vec2(0.0, 0.0), sunRadius, Planet::Material::Sun)); + for (int y=0; y<2; y++) { + for (int x=0; x 0.9) { radius = 0.9; } - } glm::vec2 pos; @@ -353,7 +396,11 @@ namespace game { void State::advance(float dt) { - //std::cout<<"[state] (init) cycle: update events length is " << m_nextEvents.size() << std::endl; + if (m_needReInit) { + m_needReInit = false; + std::cout<<"[state] need initialization of game, restarting." << std::endl; + init(); + } m_time += dt; @@ -367,19 +414,11 @@ namespace game { advancePlayerMissiles(dt); - //std::cout<<"[state] (before move) cycle: update events length is " << m_nextEvents.size() << std::endl; - // put collected events into that list. - //m_allEvents.push_back(std::move(m_nextEvents)); for (auto *evt : m_nextEvents) { m_allEvents.push_back(evt); } m_nextEvents.clear(); - - //std::cout<<"[state] (after move) cycle: update events length is " << m_nextEvents.size() << std::endl; - - // finally remove things. - //m_nextEvents.clear(); } Player *State::playerForId(size_t playerId) @@ -507,11 +546,13 @@ namespace game { void State::setPlayingFieldCenter(int center_x, int center_y) { m_playingFieldCenter = glm::vec2((float) center_x, (float) center_y); + m_needReInit = true; } void State::setPlayingFieldSize(int width, int height) { m_playingFieldSize = glm::vec2(width, height); + m_needReInit = true; } size_t State::generateId() diff --git a/game/state/state.hpp b/game/state/state.hpp index 51a9ab7..eb7228a 100644 --- a/game/state/state.hpp +++ b/game/state/state.hpp @@ -157,6 +157,8 @@ namespace game { void addExplosionFromHit(const Missile::Event *evt); bool findPlanetSpawnPosition(bool planetIsSun, float radius, glm::vec2 *pos); + void setupTestPlanets(); + void advanceTraceAges(float dt); void advanceExplosions(float dt); void advancePlayerShipSpawns(float dt); @@ -181,6 +183,7 @@ namespace game { IdGenerator m_ids; float m_time; bool m_developerMode; + bool m_needReInit; glm::vec2 m_playingFieldCenter; glm::vec2 m_playingFieldSize; diff --git a/test/shoot_n_times.py b/test/shoot_n_times.py index a73a197..c294602 100755 --- a/test/shoot_n_times.py +++ b/test/shoot_n_times.py @@ -15,7 +15,9 @@ if len(sys.argv) > 2: delay = float(sys.argv[2]) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.connect(("192.168.0.191", 3490)) +ip = "10.172.35.191" +#ip "192.168.0.191" +s.connect((ip, 3490)) for i in range(int(sys.argv[1])): a = random.randint(0, 360)