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