graphics api abstraction
[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
20 #include "opengl/opengl.h"
21 #include "vulkan/vk.h"
22
23 /* static functions */
24
25 static bool init(Gfx_API api);
26 static void cleanup();
27 static void display();
28
29 /* glfw callbacks */
30
31 static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mods);
32 static void clbk_motion(GLFWwindow *win, double x, double y);
33 static void clbk_mouse(GLFWwindow *win, int button, int action, int mods);
34 static void clbk_reshape(GLFWwindow *win, int width, int height);
35
36 /* global variables */
37
38 Mat4 mprojection;
39
40 GLFWwindow *win;
41 int win_w = 800;
42 int win_h = 600;
43
44 float phi = 25;
45 float theta = 0;
46 float dist = 4;
47
48 ShaderManager *sdr_man;
49
50 /* variables */
51
52 static float aspect;
53 static OrbitCamera *camera;
54
55 static Scene *scene_cow;
56 static Renderer *rcow;
57
58 static Scene *scene_ground;
59 static Renderer *rground; // default renderer
60
61 /* *** */
62
63 int main(int argc, char **argv)
64 {
65         Gfx_API api;
66
67         for(int i=0; i<argc; ++i) {
68                 if(strcmp(argv[i], "-opengl") == 0) {
69                         api = GFX_GL;
70                         printf("Backend: OpenGL.\n");
71                 }
72                 else if(strcmp(argv[i], "-vulkan") == 0) {
73                         api = GFX_VK;
74                         printf("Backend: Vulkan.\n");
75                 }
76                 else {
77                         api = GFX_GL;
78                         printf("No backend specified. Using OpenGL.\n");
79                 }
80         }
81
82         if(!init(api)) {
83                 fprintf(stderr, "Failed to initialize program.\n");
84                 return 1;
85         }
86
87         glfwSetKeyCallback(win, clbk_key);
88         glfwSetCursorPosCallback(win, clbk_motion);
89         glfwSetMouseButtonCallback(win, clbk_mouse);
90         glfwSetWindowSizeCallback(win, clbk_reshape);
91
92         glfwGetWindowSize(win, &win_w, &win_h);
93         clbk_reshape(win, win_w, win_h);
94
95         while(!glfwWindowShouldClose(win)) {
96                 display();
97
98                 glfwSwapBuffers(win);
99                 glfwPollEvents();
100         }
101
102         cleanup();
103         // atexit(cleanup);
104         return 0;
105 }
106
107 static bool init(Gfx_API api)
108 {
109         if(!gfx_init(api))
110                 return false;
111
112         sdr_man = new ShaderManager;
113
114         camera = new OrbitCamera;
115         camera->set_orbit_params(phi, theta, dist);
116
117         scene_ground = new Scene;
118         if(!scene_ground->load("data/ground.obj")) {
119                 fprintf(stderr, "Failed to load scene: ground.obj.\n");
120                 return false;
121         }
122
123         scene_cow = new Scene;
124         if(!scene_cow->load("data/spot/spot.obj")) {
125                 fprintf(stderr, "Failed to load scene: spot.obj.\n");
126                 return false;
127         }
128
129         rground = new Renderer;
130         rground->camera = camera;
131         rground->scene = scene_ground;
132
133         if(!rground->create()) {
134                 fprintf(stderr, "Failed to create default renderer.\n");
135                 return false;
136         }
137
138         rcow = new Renderer;
139         rcow->camera = camera;
140         rcow->scene = scene_cow;
141
142         if(!rcow->create()) {
143                 fprintf(stderr, "Failed to create renderer for cows.\n");
144                 return false;
145         }
146
147 // TODO delete: debugging
148         for(size_t i=0; i<scene_ground->objects.size(); ++i) {
149                 printf("object: %d\n", (int)i);
150                 printf("mesh: %s\n", scene_ground->objects[i]->mesh->name.c_str());
151                 printf("material: %s\n", scene_ground->objects[i]->material->name.c_str());
152                 printf("transform:\n");
153                 scene_ground->objects[i]->transform.print();
154         }
155         return true;
156 }
157
158 static void cleanup()
159 {
160         delete sdr_man;
161         delete camera;
162
163         delete scene_cow;
164         delete rcow;
165
166         delete scene_ground;
167         delete rground;
168
169         gfx_cleanup();
170 }
171
172 static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mods)
173 {
174         if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
175                 glfwSetWindowShouldClose(win, GLFW_TRUE);
176         }
177 }
178
179 static double prev_x, prev_y;
180 static bool button[8];
181
182 static void clbk_motion(GLFWwindow *win, double x, double y)
183 {
184         double dx = x - prev_x;
185         double dy = y - prev_y;
186
187         prev_x = x;
188         prev_y = y;
189
190         if(button[0]) {
191                 theta += dx;
192                 phi += dy;
193
194                 if(phi < -90)
195                         phi = -90;
196                 if(phi > 90)
197                         phi = 90;
198         }
199
200         if(button[1]) {
201                 dist += dy * 0.1;
202                 if(dist < 0.0) {
203                         dist = 0.0;
204                 }
205         }
206 }
207
208 static void clbk_mouse(GLFWwindow *win, int bn, int action, int mods)
209 {
210         button[bn] = action == GLFW_PRESS;
211         glfwGetCursorPos(win, &prev_x, &prev_y);
212 }
213
214 static void clbk_reshape(GLFWwindow *win, int width, int height)
215 {
216         gfx_viewport(0, 0, width, height);
217         aspect = (float)width / (float)height;
218         mprojection = calc_projection_matrix(45, aspect, 0.5, 1000.0);
219
220         win_h = height;
221         win_w = width;
222 }
223
224 static void display()
225 {
226         camera->set_orbit_params(phi, theta, dist);
227
228         gfx_clear(0.76, 0.3, 0.43);
229
230         rground->draw();
231         rcow->draw();
232 }