]> git.lizzy.rs Git - dragonblocks3d.git/blob - src/dragonblocks/mesh.cpp
Added player, refactored mesh code
[dragonblocks3d.git] / src / dragonblocks / mesh.cpp
1 #include <stdexcept>
2 #include <cstdlib>
3 #include <cstring>
4 #include <glm/gtc/matrix_transform.hpp>
5 #include <glm/gtc/constants.hpp>
6 #include "gldebug.hpp"
7 #include "mesh.hpp"
8 #include "scene.hpp"
9 #include "shader_program.hpp"
10
11 using namespace std;
12 using namespace glm;
13 using namespace dragonblocks;
14
15 double Mesh::Animation::grow_time = 0.25;       // s
16 double Mesh::Animation::flyin_time = 0.4;       // s
17 double Mesh::Animation::flyin_offset = 20;      // m
18 double Mesh::Animation::rotate_speed = 1;       // turns/s
19
20 mat4 Mesh::Animation::getModelMatrix(double dtime, vec3 pos, vec3 size, vec3 rotation_axis, float rotation_angle)
21 {
22         mat4 trans = mat4(1.0);
23
24         if (type == Mesh::Animation::Type::NONE)
25                 goto finish;
26
27         if (expires) {
28                 time_left -= dtime;
29                 if (time_left < 0) {
30                         type = Mesh::Animation::Type::NONE;
31                         if (on_finish) {
32                                 (*on_finish)(extra_data);
33                         }
34                         goto finish;
35                 }
36         }       
37
38         switch (type) {
39                 case Mesh::Animation::Type::FLYIN:
40                 pos.y -= Mesh::Animation::flyin_offset * time_left / Mesh::Animation::flyin_time;
41                 break;
42                 
43                 case Mesh::Animation::Type::GROW:
44                 size *= 1 - time_left / Mesh::Animation::grow_time;
45                 break;
46                 
47                 case Mesh::Animation::Type::ROTATE:
48                 rotation_angle += glfwGetTime() * Mesh::Animation::rotate_speed * pi<float>() * 2;
49         }
50
51         finish:
52         
53         trans = translate(trans, pos);
54         trans = rotate(trans, rotation_angle, rotation_axis);
55         trans = scale(trans, size);
56         
57         return trans;
58 }
59
60 Mesh::Animation::Animation(Mesh::Animation::Type t, void (*o)(void *), void *e) : type(t), on_finish(o), extra_data(e)
61 {
62         switch(type) {
63                 case Mesh::Animation::Type::FLYIN:
64                 expires = true;
65                 time_left = Mesh::Animation::flyin_time;
66                 break;
67                 
68                 case Mesh::Animation::Type::GROW:
69                 expires = true;
70                 time_left = Mesh::Animation::grow_time;
71                 break;
72                 
73                 case Mesh::Animation::Type::ROTATE:
74                 expires = false;
75                 break;
76         }
77 }
78
79 void Mesh::render(double dtime, ShaderProgram *shader_program)
80 {
81         rendering = true;
82         
83         if (do_delete) {
84                 delete this;
85                 return;
86         } else if (prepare_death) {
87                 do_delete = true;
88         }
89         
90         if (! configured) {
91                 configure();
92         }
93
94         shader_program->use(); CHECKERR
95         
96         mat4 model_matrix = animation.getModelMatrix(dtime, pos, size, rotation_axis, rotation_angle); CHECKERR
97         
98         shader_program->set("model", model_matrix); CHECKERR
99         
100         glBindVertexArray(VAO); CHECKERR
101         for (int i = 0; i < textures.size(); i++) {
102                 textures[i].bind(); CHECKERR
103                 glDrawArrays(GL_TRIANGLES, i * vertices_per_texture, vertices_per_texture); CHECKERR
104         }
105         glBindVertexArray(0); CHECKERR
106         glBindTexture(GL_TEXTURE_2D, 0); CHECKERR
107         
108         rendering = false;
109 }
110
111 bool Mesh::isRendering()
112 {
113         return rendering;
114 }
115
116 void Mesh::die()
117 {
118         prepare_death = true;
119 }
120
121 Mesh::Mesh(Scene *s, const GLvoid *v, GLsizei vs): pos(0), size(1), rotation_axis(0, 1, 0), scene(s), vertices_size(vs)
122 {
123         if (! v || ! vs)
124                 throw runtime_error("Invalid Mesh configuration");
125         vertices = malloc(vs);
126         memcpy(vertices, v, vs);
127         scene->add(this);
128 }
129
130 Mesh::~Mesh()
131 {
132         scene->remove(this);
133         if (VAO) {
134                 glDeleteVertexArrays(1, &VAO); CHECKERR
135         }
136         if (VBO) {
137                 glDeleteBuffers(1, &VAO); CHECKERR
138         }
139 }
140
141 void Mesh::configure()
142 {               
143         glGenVertexArrays(1, &VAO); CHECKERR
144         glGenBuffers(1, &VBO); CHECKERR
145         
146         glBindVertexArray(VAO); CHECKERR
147         glBindBuffer(GL_ARRAY_BUFFER, VBO); CHECKERR
148
149         glBufferData(GL_ARRAY_BUFFER, vertices_size, vertices, GL_STATIC_DRAW); CHECKERR
150         
151         GLsizei stride = 5 * sizeof(GLfloat); CHECKERR
152         
153         glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, (GLvoid *)(0 * sizeof(GLfloat))); CHECKERR
154         glEnableVertexAttribArray(0); CHECKERR
155         glVertexAttribPointer(1, 2, GL_FLOAT, false, stride, (GLvoid *)(3 * sizeof(GLfloat))); CHECKERR
156         glEnableVertexAttribArray(1); CHECKERR
157         
158         glBindBuffer(GL_ARRAY_BUFFER, 0); CHECKERR
159         glBindVertexArray(0); CHECKERR
160         
161         free(vertices);
162         vertices = NULL;
163         configured = true;
164 }