forked from drahosp/ppgso
-
Notifications
You must be signed in to change notification settings - Fork 5
/
gl9_scene.cpp
174 lines (143 loc) · 4.53 KB
/
gl9_scene.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Example gl_scene
// - Introduces the concept of a dynamic scene of objects
// - Uses abstract object interface for Update and Render steps
// - Creates a simple game scene with Player, Asteroid and Space objects
// - Contains a generator object that does not render but adds Asteroids to the scene
// - Some objects use shared resources and all object deallocations are handled automatically
// - Controls: LEFT, RIGHT, "R" to reset, SPACE to fire
#include <iostream>
#include <map>
#include <list>
#include <ppgso/ppgso.h>
#include "camera.h"
#include "scene.h"
#include "generator.h"
#include "player.h"
#include "space.h"
const unsigned int SIZE = 512;
/*!
* Custom windows for our simple game
*/
class SceneWindow : public ppgso::Window {
private:
Scene scene;
bool animate = true;
/*!
* Reset and initialize the game scene
* Creating unique smart pointers to objects that are stored in the scene object list
*/
void initScene() {
scene.objects.clear();
// Create a camera
auto camera = std::make_unique<Camera>(60.0f, 1.0f, 0.1f, 100.0f);
camera->position.z = -15.0f;
scene.camera = move(camera);
// Add space background
scene.objects.push_back(std::make_unique<Space>());
// Add generator to scene
auto generator = std::make_unique<Generator>();
generator->position.y = 10.0f;
scene.objects.push_back(move(generator));
// Add player to the scene
auto player = std::make_unique<Player>();
player->position.y = -6;
scene.objects.push_back(move(player));
}
public:
/*!
* Construct custom game window
*/
SceneWindow() : Window{"gl9_scene", SIZE, SIZE} {
//hideCursor();
glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
// Initialize OpenGL state
// Enable Z-buffer
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// Enable polygon culling
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
initScene();
}
/*!
* Handles pressed key when the window is focused
* @param key Key code of the key being pressed/released
* @param scanCode Scan code of the key being pressed/released
* @param action Action indicating the key state change
* @param mods Additional modifiers to consider
*/
void onKey(int key, int scanCode, int action, int mods) override {
scene.keyboard[key] = action;
// Reset
if (key == GLFW_KEY_R && action == GLFW_PRESS) {
initScene();
}
// Pause
if (key == GLFW_KEY_P && action == GLFW_PRESS) {
animate = !animate;
}
}
/*!
* Handle cursor position changes
* @param cursorX Mouse horizontal position in window coordinates
* @param cursorY Mouse vertical position in window coordinates
*/
void onCursorPos(double cursorX, double cursorY) override {
scene.cursor.x = cursorX;
scene.cursor.y = cursorY;
}
/*!
* Handle cursor buttons
* @param button Mouse button being manipulated
* @param action Mouse bu
* @param mods
*/
void onMouseButton(int button, int action, int mods) override {
if(button == GLFW_MOUSE_BUTTON_LEFT) {
scene.cursor.left = action == GLFW_PRESS;
if (scene.cursor.left) {
// Convert pixel coordinates to Screen coordinates
double u = (scene.cursor.x / width - 0.5f) * 2.0f;
double v = - (scene.cursor.y / height - 0.5f) * 2.0f;
// Get mouse pick vector in world coordinates
auto direction = scene.camera->cast(u, v);
auto position = scene.camera->position;
// Get all objects in scene intersected by ray
auto picked = scene.intersect(position, direction);
// Go through all objects that have been picked
for (auto &obj: picked) {
// Pass on the click event
obj->onClick(scene);
}
}
}
if(button == GLFW_MOUSE_BUTTON_RIGHT) {
scene.cursor.right = action == GLFW_PRESS;
}
}
/*!
* Window update implementation that will be called automatically from pollEvents
*/
void onIdle() override {
// Track time
static auto time = (float) glfwGetTime();
// Compute time delta
float dt = animate ? (float) glfwGetTime() - time : 0;
time = (float) glfwGetTime();
// Set gray background
glClearColor(.5f, .5f, .5f, 0);
// Clear depth and color buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Update and render all objects
scene.update(dt);
scene.render();
}
};
int main() {
// Initialize our window
SceneWindow window;
// Main execution loop
while (window.pollEvents()) {}
return EXIT_SUCCESS;
}