-
Notifications
You must be signed in to change notification settings - Fork 0
/
Scene.hpp
138 lines (112 loc) · 4.67 KB
/
Scene.hpp
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
#pragma once
/*
* A scene manages a hierarchical arrangement of transformations (via "Transform").
*
* Each transformation may have associated:
* - Drawing data (via "Drawable")
* - Camera information (via "Camera")
* - Light information (via "Lamp")
*
* This associated information
*
*/
#include "GL.hpp"
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <list>
#include <memory>
#include <functional>
#include <string>
#include <vector>
struct Scene {
struct Transform {
//Transform names are useful for debugging and looking up locations in a loaded scene:
std::string name;
//The core function of a transform is to store a transformation in the world:
glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f); //n.b. wxyz init order
glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f);
//The transform above may be relative to some parent transform:
Transform *parent = nullptr;
//It is often convenient to construct matrices representing this transformation:
// ..relative to its parent:
glm::mat4 make_local_to_parent() const;
glm::mat4 make_parent_to_local() const;
// ..relative to the world:
glm::mat4 make_local_to_world() const;
glm::mat4 make_world_to_local() const;
//since hierarchy is tracked through pointers, copy-constructing a transform is not advised:
Transform(Transform const &) = delete;
//if we delete some constructors, we need to let the compiler know that the default constructor is still okay:
Transform() = default;
};
struct Drawable {
//a 'Drawable' attaches attribute data to a transform:
Drawable(Transform *transform_) : transform(transform_) { assert(transform); }
Transform * transform;
//Contains all the data needed to run the OpenGL pipeline:
struct Pipeline {
GLuint program = 0; //shader program; passed to glUseProgram
//attributes:
GLuint vao = 0; //attrib->buffer mapping; passed to glBindVertexArray
GLenum type = GL_TRIANGLES; //what sort of primitive to draw; passed to glDrawArrays
GLuint start = 0; //first vertex to draw; passed to glDrawArrays
GLuint count = 0; //number of vertices to draw; passed to glDrawArrays
//uniforms:
GLuint OBJECT_TO_CLIP_mat4 = -1U; //uniform location for object to clip space matrix
GLuint OBJECT_TO_LIGHT_mat4x3 = -1U; //uniform location for object to light space (== world space) matrix
GLuint NORMAL_TO_LIGHT_mat3 = -1U; //uniform location for normal to light space (== world space) matrix
std::function< void() > set_uniforms; //(optional) function to set any other useful uniforms
//texture objects to bind for the first TextureCount textures:
enum : uint32_t { TextureCount = 4 };
struct TextureInfo {
GLuint texture = 0;
GLenum target = GL_TEXTURE_2D;
} textures[TextureCount];
} pipeline;
};
struct Camera {
//a 'Camera' attaches camera data to a transform:
Camera(Transform *transform_) : transform(transform_) { assert(transform); }
Transform * transform;
//NOTE: cameras are directed along their -z axis
//perspective camera parameters:
float fovy = glm::radians(60.0f); //vertical fov (in radians)
float aspect = 1.0f; //x / y
float near = 0.01f; //near plane
//computed from the above:
glm::mat4 make_projection() const;
};
struct Lamp {
//a 'Lamp' attaches light data to a transform:
Lamp(Transform *transform_) : transform(transform_) { assert(transform); }
Transform * transform;
//NOTE: directional, spot, and hemisphere lights are directed along their -z axis
enum Type : char {
Point = 'p',
Hemisphere = 'h',
Spot = 's',
Directional = 'd'
} type = Point;
//light energy at our conventional three wavelengths:
glm::vec3 energy = glm::vec3(1.0f);
//Spotlight specific:
float spot_fov = glm::radians(45.0f);
};
//Scenes, of course, may have many of the above objects:
std::list< Transform > transforms;
std::vector< Drawable > drawables;
std::list< Camera > cameras;
std::list< Lamp > lamps;
//The "draw" function provides a convenient way to pass all the things in a scene to OpenGL:
void draw(Camera const &camera) const;
void draw(Camera const &camera, Transform const &trans) const;
//..sometimes, you want to draw with a custom projection matrix and/or light space:
void draw(glm::mat4 const &world_to_clip, glm::mat4x3 const &world_to_light = glm::mat4x3(1.0f)) const;
//add transforms/objects/cameras from a scene file to this scene:
// the 'on_drawable' callback gives your code a chance to look up mesh data and make Drawables:
// throws on file format errors
void load(std::string const &filename,
std::function< void(Scene &, Transform *, std::string const &) > const &on_drawable = nullptr
);
};