forked from ixchow/15-466-f17-base2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Meshes.cpp
127 lines (112 loc) · 3.92 KB
/
Meshes.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
#include "Meshes.hpp"
#include "read_chunk.hpp"
#include <glm/glm.hpp>
#include <stdexcept>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
void Meshes::load(std::string const &filename, Attributes const &attributes) {
std::ifstream file(filename, std::ios::binary);
GLuint vao = 0;
GLuint total = 0;
{ //read + upload data chunk:
struct v3n3u2 {
glm::vec3 v;
glm::vec3 n;
glm::vec2 uvcoord;
};
static_assert(sizeof(v3n3u2) == 32, "v3n3u2 is packed");
std::vector< v3n3u2 > data;
read_chunk(file, "v3n3", &data);
//upload data:
GLuint buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(v3n3u2) * data.size(), &data[0], GL_STATIC_DRAW);
total = data.size(); //store total for later checks on index
//store binding:
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
if (attributes.Position != -1U) {
glVertexAttribPointer(attributes.Position, 3, GL_FLOAT, GL_FALSE, sizeof(v3n3u2), (GLbyte *)0);
glEnableVertexAttribArray(attributes.Position);
} else {
std::cerr << "WARNING: loading v3n3u2 data from '" << filename << "', but not using the Position attribute." << std::endl;
}
if (attributes.Normal != -1U) {
glVertexAttribPointer(attributes.Normal, 3, GL_FLOAT, GL_FALSE, sizeof(v3n3u2), (GLbyte *)0 + sizeof(glm::vec3));
glEnableVertexAttribArray(attributes.Normal);
} else {
std::cerr << "WARNING: loading v3n3u2 data from '" << filename << "', but not using the Normal attribute." << std::endl;
}
if (attributes.UVCoord != -1U) {
glVertexAttribPointer(attributes.UVCoord, 2, GL_FLOAT, GL_FALSE, sizeof(v3n3u2), (GLbyte *)0 + sizeof(glm::vec3) * 2);
glEnableVertexAttribArray(attributes.UVCoord);
} else {
std::cerr << "WARNING: loading v3n3u2 data from '" << filename << "', but not using the UVCoord attribute." << std::endl;
}
}
std::vector< char > strings;
read_chunk(file, "str0", &strings);
{ //read index chunk, add to meshes:
struct IndexEntry {
uint32_t name_begin, name_end;
uint32_t vertex_start, vertex_count;
};
static_assert(sizeof(IndexEntry) == 16, "Index entry should be packed");
std::vector< IndexEntry > index;
read_chunk(file, "idx0", &index);
for (auto const &entry : index) {
if (!(entry.name_begin <= entry.name_end && entry.name_end <= strings.size())) {
throw std::runtime_error("index entry has out-of-range name begin/end");
}
if (!(entry.vertex_start < entry.vertex_start + entry.vertex_count && entry.vertex_start + entry.vertex_count <= total)) {
throw std::runtime_error("index entry has out-of-range vertex start/count");
}
std::string name(&strings[0] + entry.name_begin, &strings[0] + entry.name_end);
Mesh mesh;
mesh.vao = vao;
mesh.start = entry.vertex_start;
mesh.count = entry.vertex_count;
/*
mesh.max = data[mesh.start].v;
mesh.min = data[mesh.start].v;
for (auto i = mesh.start; i < mesh.start + mesh.count; i++) {
if (mesh.max.x > data[i].v.x) {
mesh.max.x = data[i].v.x;
}
if (mesh.max.y > data[i].v.y) {
mesh.max.y = data[i].v.y;
}
if (mesh.max.z > data[i].v.z) {
mesh.max.z = data[i].v.z;
}
if (mesh.max.x > data[i].v.x) {
mesh.max.x = data[i].v.x;
}
if (mesh.max.y > data[i].v.y) {
mesh.max.y = data[i].v.y;
}
if (mesh.max.z > data[i].v.z) {
mesh.max.z = data[i].v.z;
}
}
*/
bool inserted = meshes.insert(std::make_pair(name, mesh)).second;
if (!inserted) {
std::cerr << "WARNING: mesh name '" + name + "' in filename '" + filename + "' collides with existing mesh." << std::endl;
}
}
}
if (file.peek() != EOF) {
std::cerr << "WARNING: trailing data in mesh file '" + filename + "'" << std::endl;
}
}
Mesh const &Meshes::get(std::string const &name) const {
auto f = meshes.find(name);
if (f == meshes.end()) {
throw std::runtime_error("Looking up mesh that doesn't exist.");
}
return f->second;
}