-
Notifications
You must be signed in to change notification settings - Fork 5
/
mesh.cpp
140 lines (120 loc) · 4.45 KB
/
mesh.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
#include "mesh.h"
#include <glm/gtc/matrix_transform.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <vector>
Mesh::Mesh()
: numMeshes(1)
{
}
Mesh::~Mesh()
{
if(vao)
{
glDeleteVertexArrays(1, &vao);
}
}
bool Mesh::load(const char* fileName)
{
if(vao)
{
// Already loaded
return false;
}
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(fileName,
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType);
if(!scene)
{
std::cerr << "Error loading mesh " << fileName << ": " << importer.GetErrorString() << std::endl;
return false;
}
// We only load the first mesh from the Assimp scene here
std::vector<float> vertices;
std::vector<GLuint> indices;
const aiMesh* mesh = scene->mMeshes[0];
for(int i = 0; i < mesh->mNumVertices; ++i)
{
const aiVector3D* pos = &(mesh->mVertices[i]);
const aiVector3D* texCoord = &(mesh->mTextureCoords[0][i]);
const aiVector3D* normal = &(mesh->mNormals[i]);
vertices.push_back(pos->x);
vertices.push_back(pos->y);
vertices.push_back(pos->z);
vertices.push_back(normal->x);
vertices.push_back(normal->y);
vertices.push_back(normal->z);
vertices.push_back(texCoord->x);
vertices.push_back(texCoord->y);
}
for(int i = 0; i < mesh->mNumFaces; ++i)
{
const aiFace* face = &(mesh->mFaces[i]);
indices.push_back(face->mIndices[0]);
indices.push_back(face->mIndices[1]);
indices.push_back(face->mIndices[2]);
}
numIndices = indices.size();
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLuint ebo;
glGenBuffers(1, &ebo);
// Upload the vertices to the buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
// Upload the indices to the buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &indices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(1); // normal
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); // texture coordinates
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
// We have now successfully created a drawable Vertex Array Object
glBindVertexArray(0);
// We no longer need the buffers
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
return true;
}
void Mesh::setInstances(int numMeshes, std::vector<glm::mat4> models)
{
this->numMeshes = numMeshes;
glBindVertexArray(vao);
// Create a buffer for the model matrices
GLuint mbo;
glGenBuffers(1, &mbo);
glBindBuffer(GL_ARRAY_BUFFER, mbo);
// Send all the model matrices to the GPU
glBufferData(GL_ARRAY_BUFFER, numMeshes * sizeof(glm::mat4), &models[0], GL_STATIC_DRAW);
// If you look at the shader, you will see "layout(location=3) in mat4 model_inst"
// OpenGL only allows a maximum of vec4 passing through glVertexAttribPointer,
// so we have to pass 4 vec4s to pass a matrix
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4)));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4)));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4)));
// Update the matrix (3, 4, , 65) for every 1 instance
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);
glBindVertexArray(0);
glDeleteBuffers(1, &mbo);
}
void Mesh::render()
{
glBindVertexArray(vao);
glDrawElementsInstanced(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0, numMeshes);
glBindVertexArray(0);
}