ixenroh

Untitled

Nov 5th, 2020
457
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.45 KB | None | 0 0
  1. // Task 7 - Dynamically generate objects in a 3D scene
  2. // - Implement a particle system where particles have position and speed
  3. // - Any object can be a generator and can add objects to the scene
  4. // - Create dynamic effect such as fireworks, rain etc.
  5. // - Encapsulate camera in a class
  6.  
  7. #include <iostream>
  8. #include <memory>
  9. #include <vector>
  10. #include <map>
  11. #include <list>
  12.  
  13. #define GLM_ENABLE_EXPERIMENTAL
  14.  
  15. #include <glm/glm.hpp>
  16. #include <glm/gtc/matrix_transform.hpp>
  17. #include <glm/gtx/euler_angles.hpp>
  18. #include <glm/gtx/transform.hpp>
  19.  
  20. #include <ppgso/ppgso.h>
  21.  
  22. #include <shaders/color_vert_glsl.h>
  23. #include <shaders/color_frag_glsl.h>
  24.  
  25. const unsigned int SIZE = 512;
  26.  
  27. class Camera {
  28. public:
  29. // TODO: Add parameters
  30. glm::mat4 viewMatrix;
  31. glm::mat4 projectionMatrix;
  32.  
  33. /// Representaiton of
  34. /// \param fov - Field of view (in degrees)
  35. /// \param ratio - Viewport ratio (width/height)
  36. /// \param near - Distance of the near clipping plane
  37. /// \param far - Distance of the far clipping plane
  38. Camera(float fov = 45.0f, float ratio = 1.0f, float near = 0.1f, float far = 10.0f) {
  39. // TODO: Initialize perspective projection (hint: glm::perspective)
  40. projectionMatrix = glm::perspective((ppgso::PI / 180.f) * fov, ratio, near, far);
  41. }
  42.  
  43. /// Recalculate viewMatrix from position, rotation and scale
  44. void update() {
  45. viewMatrix = glm::lookAt(glm::vec3{1, 0, 0}, glm::vec3{0, 1.5, -6}, glm::vec3{0, 1, 0});
  46. }
  47. };
  48.  
  49. /// Abstract renderable object interface
  50. class Renderable; // Forward declaration for Scene
  51. using Scene = std::list<std::unique_ptr<Renderable>>; // Type alias
  52.  
  53. class Renderable {
  54. public:
  55. // Virtual destructor is needed for abstract interfaces
  56. virtual ~Renderable() = default;
  57.  
  58. /// Render the object
  59. /// \param camera - Camera to use for rendering
  60. virtual void render(const Camera &camera) = 0;
  61.  
  62. /// Update the object. Useful for specifing animation and behaviour.
  63. /// \param dTime - Time delta
  64. /// \param scene - Scene reference
  65. /// \return - Return true to keep object in scene
  66. virtual bool update(float dTime, Scene &scene) = 0;
  67. };
  68.  
  69. class ParticleCorona final : public Renderable {
  70.  
  71. // Static resources shared between all particles
  72. static std::unique_ptr<ppgso::Mesh> mesh;
  73. static std::unique_ptr<ppgso::Shader> program;
  74. public:
  75.  
  76. glm::vec3 velocity;
  77. glm::vec3 acceleration;
  78. glm::vec3 position;
  79. glm::vec3 scale;
  80. glm::vec3 color;
  81.  
  82.  
  83. glm::mat4 modelMatrix;
  84.  
  85. void init(glm::vec3 pos, glm::vec3 clr, glm::vec3 spd, float size){
  86. velocity = {spd.x, spd.y, spd.z};
  87. acceleration = {1.5, 0, 0};
  88. scale = {size, size, size};
  89. position = {pos.x, pos.y, pos.z};
  90. color = {clr.x, clr.y, clr.z};
  91. *program = {color_vert_glsl, color_frag_glsl};
  92. modelMatrix = glm::mat4{1.0f};
  93. }
  94.  
  95. bool update(float dTime, Scene &scene) override {
  96. if(velocity.x >= 0)
  97. return false;
  98.  
  99. velocity.x = acceleration.x * dTime;
  100. velocity.y = acceleration.y * dTime;
  101. velocity.z = acceleration.z * dTime;
  102.  
  103. position.x += velocity.x;
  104. position.y += velocity.y;
  105. position.z += velocity.z;
  106.  
  107. modelMatrix = glm::translate(position);
  108.  
  109. return true;
  110. }
  111.  
  112. void render(const Camera &camera) override {
  113.  
  114. program->setUniform("OverallColor", color);
  115. program->setUniform("ModelMatrix", modelMatrix);
  116. program->setUniform("ViewMatrix", camera.viewMatrix);
  117. program->setUniform("ProjectionMatrix", camera.projectionMatrix);
  118.  
  119. mesh->render();
  120. }
  121.  
  122. ParticleCorona(glm::vec3 position, glm::vec3 color, glm::vec3 speed, float scl){
  123. init(position, color, speed, scl);
  124. if (!program) program = std::make_unique<ppgso::Shader>(color_vert_glsl, color_frag_glsl);
  125. if (!mesh) mesh = std::make_unique<ppgso::Mesh>("sphere.obj");
  126. }
  127. };
  128.  
  129. class ParticleWater final : public Renderable {
  130. // Static resources shared between all particles
  131. static std::unique_ptr<ppgso::Mesh> mesh;
  132. static std::unique_ptr<ppgso::Shader> program;
  133. public:
  134.  
  135. glm::vec3 velocity;
  136. glm::vec3 acceleration;
  137. glm::vec3 position;
  138. glm::vec3 scale;
  139. glm::vec3 color;
  140.  
  141. double tts = 0.5;
  142.  
  143. glm::mat4 modelMatrix;
  144.  
  145. void init(glm::vec3 pos, glm::vec3 clr, float size){
  146. velocity = {-8, static_cast <float> (rand()) / static_cast <float> (RAND_MAX), static_cast <float> (rand()) / static_cast <float> (RAND_MAX) / 2 - 1.};
  147. acceleration = {1, -9.81, 0};
  148. scale = {size, size, size};
  149. position = {pos.x, pos.y, pos.z};
  150. color = {clr.x, clr.y, clr.z};
  151. *program = {color_vert_glsl, color_frag_glsl};
  152. modelMatrix = glm::mat4{1.0f};
  153. }
  154.  
  155. bool update(float dTime, Scene &scene) override {
  156. if(position.y <= 0)
  157. return false;
  158.  
  159. velocity.x = acceleration.x * dTime;
  160. velocity.y = acceleration.y * dTime;
  161. velocity.z = acceleration.z * dTime;
  162.  
  163. position.x += velocity.x;
  164. position.y += velocity.y;
  165. position.z += velocity.z;
  166.  
  167. if(tts <= 0 && tts >= -1){
  168. std::unique_ptr<ParticleCorona> ptr(new ParticleCorona{position, {0, 1, 0}, velocity, 0.2f});
  169. scene.push_back(std::move(ptr));
  170. }
  171. tts -= dTime;
  172.  
  173. modelMatrix = glm::translate(position);
  174.  
  175. return true;
  176. }
  177.  
  178. void render(const Camera &camera) override {
  179.  
  180. program->setUniform("OverallColor", color);
  181. program->setUniform("ModelMatrix", modelMatrix);
  182. program->setUniform("ViewMatrix", camera.viewMatrix);
  183. program->setUniform("ProjectionMatrix", camera.projectionMatrix);
  184.  
  185. mesh->render();
  186. }
  187.  
  188. ParticleWater(glm::vec3 position, glm::vec3 color, float scl){
  189. init(position, color, scl);
  190. if (!program) program = std::make_unique<ppgso::Shader>(color_vert_glsl, color_frag_glsl);
  191. if (!mesh) mesh = std::make_unique<ppgso::Mesh>("sphere.obj");
  192. }
  193. };
  194.  
  195. // Static resources need to be instantiated outside of the class as they are globals
  196. std::unique_ptr<ppgso::Mesh> ParticleWater::mesh;
  197. std::unique_ptr<ppgso::Shader> ParticleWater::program;
  198.  
  199. std::unique_ptr<ppgso::Mesh> ParticleCorona::mesh;
  200. std::unique_ptr<ppgso::Shader> ParticleCorona::program;
  201.  
  202. class ParticleWindow : public ppgso::Window {
  203. private:
  204. // Scene of objects
  205. Scene scene;
  206.  
  207. // Create camera
  208. Camera camera = {120.0f, (float) width / (float) height, 1.0f, 400.0f};
  209.  
  210. // Store keyboard state
  211. std::map<int, int> keys;
  212. public:
  213. ParticleWindow() : Window{"task7_particles", SIZE, SIZE} {
  214. // Initialize OpenGL state
  215. // Enable Z-buffer
  216. glEnable(GL_DEPTH_TEST);
  217. glDepthFunc(GL_LEQUAL);
  218. }
  219.  
  220. void onKey(int key, int scanCode, int action, int mods) override {
  221. // Collect key state in a map
  222. keys[key] = action;
  223. if (keys[GLFW_KEY_SPACE]) {
  224. auto particle = std::make_unique<ParticleWater>({2, 2, -6}, {0, 0, 1}, 0.4f});
  225. scene.push_back(std::move(particle));
  226. }
  227. }
  228.  
  229. void onIdle() override {
  230. // Track time
  231. static auto time = (float) glfwGetTime();
  232. // Compute time delta
  233. float dTime = (float) glfwGetTime() - time;
  234. time = (float) glfwGetTime();
  235.  
  236. // Set gray background
  237. glClearColor(.1f, .1f, .1f, 1.0f);
  238.  
  239. // Clear depth and color buffers
  240. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  241.  
  242. // Update all objects in scene
  243. // Because we need to delete while iterating this is implemented using c++ iterators
  244. // In most languages mutating the container during iteration is undefined behaviour
  245. auto i = std::begin(scene);
  246. while (i != std::end(scene)) {
  247. // Update object and remove from list if needed
  248. auto obj = i->get();
  249. if (!obj->update(dTime, scene))
  250. i = scene.erase(i);
  251. else
  252. ++i;
  253. }
  254.  
  255. // Render every object in scene
  256. for (auto &object : scene) {
  257. object->render(camera);
  258. }
  259. }
  260. };
  261.  
  262. int main() {
  263. // Create new window
  264. auto window = ParticleWindow{};
  265.  
  266. // Main execution loop
  267. while (window.pollEvents()) {}
  268.  
  269. return EXIT_SUCCESS;
  270. }
  271.  
Advertisement
Add Comment
Please, Sign In to add comment