e5572e25f94cf8342f1fe230e1aafed9d07dff92
[demo] / src / main.cc
1 #include <GL/glew.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <vector>
7
8 #include <gmath/gmath.h>
9
10 #include "gfxapi.h"
11 #include "global.h"
12
13 /* TODO: fix those */
14 #include "camera.h"
15 #include "mesh.h"
16 #include "object.h"
17 #include "renderer.h"
18 #include "scene.h"
19 #include "terrain.h"
20 #include "texture.h"
21
22 #include "opengl/opengl.h"
23 #include "vulkan/vk.h"
24
25 /* static functions */
26
27 static bool init(Gfx_API api);
28 static void cleanup();
29 static void display();
30
31 /* glfw callbacks */
32
33 static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mods);
34 static void clbk_motion(GLFWwindow *win, double x, double y);
35 static void clbk_mouse(GLFWwindow *win, int button, int action, int mods);
36 static void clbk_reshape(GLFWwindow *win, int width, int height);
37
38 /* global variables */
39
40 Mat4 mprojection;
41
42 GLFWwindow *win;
43 int win_w = 800;
44 int win_h = 600;
45
46 float phi = 25;
47 float theta = 0;
48 float dist = 16;
49
50 ShaderManager *sdr_man;
51
52 /* variables */
53
54 static float aspect;
55 static OrbitCamera *camera;
56
57 static Scene *cow_scene;
58 static Renderer *cow_rend;
59
60 static Scene *ground_scene;
61 static Renderer *ground_rend; // default renderer
62 static Texture *skybox_tex;
63
64 static Renderer *terrain_rend;
65 static Material terrain_mat;
66 static Texture *terrain_tex;
67 static Terrain terrain;
68
69 /* *** */
70
71 int main(int argc, char **argv)
72 {
73         Gfx_API api;
74
75         for(int i=0; i<argc; ++i) {
76                 if(strcmp(argv[i], "-opengl") == 0) {
77                         api = GFX_GL;
78                         printf("Backend: OpenGL.\n");
79                 }
80                 else if(strcmp(argv[i], "-vulkan") == 0) {
81                         api = GFX_VK;
82                         printf("Backend: Vulkan.\n");
83                 }
84                 else {
85                         api = GFX_GL;
86                         printf("No backend specified. Using OpenGL.\n");
87                 }
88         }
89
90         if(!init(api)) {
91                 fprintf(stderr, "Failed to initialize program.\n");
92                 return 1;
93         }
94
95         glfwSetKeyCallback(win, clbk_key);
96         glfwSetCursorPosCallback(win, clbk_motion);
97         glfwSetMouseButtonCallback(win, clbk_mouse);
98         glfwSetWindowSizeCallback(win, clbk_reshape);
99
100         glfwGetWindowSize(win, &win_w, &win_h);
101         clbk_reshape(win, win_w, win_h);
102
103         while(!glfwWindowShouldClose(win)) {
104                 display();
105
106                 glfwSwapBuffers(win);
107                 glfwPollEvents();
108         }
109
110         cleanup();
111         // atexit(cleanup);
112         return 0;
113 }
114
115 static bool init(Gfx_API api)
116 {
117         if(!gfx_init(api))
118                 return false;
119
120         sdr_man = new ShaderManager;
121
122         camera = new OrbitCamera;
123
124         // ground_scene = new Scene;
125         // if(!ground_scene->load("data/ground.obj")) {
126         //      fprintf(stderr, "Failed to load scene: ground.obj.\n");
127         //      return false;
128         // }
129
130         // ground_rend = new Renderer;
131         // ground_rend->camera = camera;
132         // ground_rend->scene = ground_scene;
133
134         // if(!ground_rend->create()) {
135         //      fprintf(stderr, "Failed to create default renderer.\n");
136         //      return false;
137         // }
138
139         // skybox_tex = gfx_create_texture();
140         // skybox_tex->load("data/cubemap/cubemap.hdr");
141         // ground_rend->set_sky_tex(skybox_tex);
142
143         cow_scene = new Scene;
144         if(!cow_scene->load("data/spot/spot.obj")) {
145                 fprintf(stderr, "Failed to load scene: spot.obj.\n");
146                 return false;
147         }
148
149         cow_rend = new Renderer;
150         cow_rend->camera = camera;
151         cow_rend->scene = cow_scene;
152
153         if(!cow_rend->create()) {
154                 fprintf(stderr, "Failed to create renderer for cows.\n");
155                 return false;
156         }
157
158         terrain_tex = gfx_create_texture();
159         if(!terrain_tex->load("data/grass.jpeg")) {
160                 fprintf(stderr, "Failed to load ground texture.\n");
161                 return false;
162         }
163
164         Image ter_hmap;
165         if(!ter_hmap.load("data/terhmap.png")) {
166                 fprintf(stderr, "Failed to load terrain heightmap.\n");
167                 return false;
168         }
169
170         TerrainParams p;
171         p.xsz = 50;
172         p.ysz = 50;
173         p.max_height = 5;
174         p.xtiles = 20;
175         p.ytiles = 20;
176         p.tile_usub = 10;
177         p.tile_vsub = 10;
178         p.num_octaves = 3;
179         p.noise_freq = 10;
180         p.coarse_heightmap = &ter_hmap;
181
182         terrain.init();
183         terrain.generate(p);
184
185         terrain_mat.diffuse = Vec3(1, 1, 1);
186         terrain_mat.specular = Vec3(0, 0, 0);
187         terrain_mat.shininess = 40;
188         terrain_mat.dtex = terrain_tex;
189         terrain_mat.name = "tt";
190
191         terrain.material = terrain_mat;
192
193         terrain_rend = new Renderer;
194         terrain_rend->camera = camera;
195         terrain_rend->scene = terrain.get_visible(camera);
196         if(!terrain_rend->create()) {
197                 fprintf(stderr, "terrain fail\n");
198                 return false;
199         }
200
201
202 // TODO delete: debugging
203         // for(size_t i=0; i<ground_scene->objects.size(); ++i) {
204         //      printf("object: %d\n", (int)i);
205         //      printf("mesh: %s\n", ground_scene->objects[i]->mesh->name.c_str());
206         //      printf("material: %s\n", ground_scene->objects[i]->material->name.c_str());
207         //      printf("transform:\n");
208         //      ground_scene->objects[i]->transform.print();
209         // }
210         return true;
211 }
212
213 static void cleanup()
214 {
215         delete sdr_man;
216         delete camera;
217
218         delete cow_scene;
219         delete cow_rend;
220
221         // delete ground_scene;
222         // delete ground_rend;
223
224 //TODO
225         delete terrain_tex;
226         delete terrain_rend;
227         gfx_cleanup();
228 }
229
230 static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mods)
231 {
232         if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
233                 glfwSetWindowShouldClose(win, GLFW_TRUE);
234         }
235 }
236
237 static double prev_x, prev_y;
238 static bool button[8];
239
240 static void clbk_motion(GLFWwindow *win, double x, double y)
241 {
242         double dx = x - prev_x;
243         double dy = y - prev_y;
244
245         prev_x = x;
246         prev_y = y;
247
248         if(button[0]) {
249                 theta += dx * 0.5;
250                 phi += dy * 0.5;
251
252                 if(phi < 0)
253                         phi = 0;
254                 if(phi > 90)
255                         phi = 90;
256         }
257
258         if(button[1]) {
259                 dist += dy * 0.1;
260                 if(dist < 0.0) {
261                         dist = 0.0;
262                 }
263         }
264 }
265
266 static void clbk_mouse(GLFWwindow *win, int bn, int action, int mods)
267 {
268         button[bn] = action == GLFW_PRESS;
269         glfwGetCursorPos(win, &prev_x, &prev_y);
270 }
271
272 static void clbk_reshape(GLFWwindow *win, int width, int height)
273 {
274         gfx_viewport(0, 0, width, height);
275         aspect = (float)width / (float)height;
276         mprojection = calc_projection_matrix(45, aspect, 0.5, 1000.0);
277
278         win_h = height;
279         win_w = width;
280 }
281
282 static void display()
283 {
284         camera->set_orbit_params(theta, phi, dist);
285
286         // gfx_clear(0.76, 0.3, 0.43);
287         gfx_clear(0.1, 0.1, 0.1);
288
289         terrain_rend->draw();
290 //      ground_rend->draw();
291         cow_rend->draw();
292 }