-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasic_obj_reader.h
More file actions
181 lines (154 loc) · 3.74 KB
/
basic_obj_reader.h
File metadata and controls
181 lines (154 loc) · 3.74 KB
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
175
176
177
178
179
180
181
#pragma once
/*
* Author: Jaime Rivera
* Date : 2020.04.20
* Copyright : Copyright 2020 Jaime Rivera | www.jaimervq.com
* Brief: Basic implementation of a obj files reader
*/
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "shapes_3D.h"
class ObjReader
{
private:
// Reading
std::string source_file;
bool invert_y;
// Geometry
std::vector<Face> faces;
BoundingBox bounding_box;
// Edge pool (just for drawing purposes)
std::vector<Edge> edge_pool;
// Polycount and general feedback
int face_count;
int vertex_count;
public:
// Constructor
ObjReader(std::string input_file) : source_file(input_file), invert_y(true), face_count(0), vertex_count(0)
{
read_from_file();
clear_edge_pool();
calculate_bb();
to_center();
}
// Read from file
void read_from_file()
{
std::ifstream f{this->source_file};
if (!f.is_open())
return;
std::vector<Vect3> temp_vertices;
while (!f.eof())
{
char line[512];
f.getline(line, 512);
std::stringstream s;
s << line;
char type;
if (line[0] == 'v' && line[1] == ' ')
{
double vx, vy, vz;
s >> type >> vx >> vy >> vz;
if (invert_y)
vy *= -1;
Vect3 vert{vx, vy, vz};
temp_vertices.push_back(vert);
this->vertex_count++;
}
else if (line[0] == 'f')
{
Face f;
std::string face_data;
s >> type;
while (s >> face_data)
{
std::string face_index;
for (char c : face_data)
{
if (c == '/')
break;
face_index += c;
}
int idx = std::stoi(face_index) - 1;
f.add_vertex(temp_vertices[idx]);
}
this->faces.push_back(f);
this->face_count++;
// Edges
for (int i = 1; i < f.count_vertices(); i++)
{
Edge e{f[i - 1], f[i]};
this->edge_pool.push_back(e);
}
Edge e_closure{f[f.count_vertices() - 1], f[0]};
this->edge_pool.push_back(e_closure);
}
}
f.close();
// Printing feedback
printf("[INFO] Total faces: %i, Total vertices: %i\n", this->face_count, this->vertex_count);
}
// Get
std::vector<Face> &get_faces() { return this->faces; }
BoundingBox &get_bb() { return this->bounding_box; }
int count_total_faces() { return this->face_count; }
int count_total_vertices() { return this->vertex_count; }
// Utility for drawing
std::vector<Edge> get_edge_pool() { return this->edge_pool; }
// Transformations
void to_center()
{
// Calculating displacement
Vect3 displacement = bounding_box.get_center().get_inverted();
if (displacement.get_magnitude() > 0.0)
printf("[WARNING] The center of the obj's bounding box was off-center.\n"
" Displacing it back to center {%f, %f, %f}\n",
displacement.get_x(), displacement.get_y(), displacement.get_z());
// Moving faces and BB
for (Face f : this->faces)
{
f.move(displacement);
}
this->bounding_box.move(displacement);
// Moving edge pool
for (Edge &e : this->edge_pool)
{
e.move(displacement);
}
}
void rotate_around_axis(double angle, Vect3 axis)
{
for (Face &f : this->get_faces())
{
f.rotate_around_axis(angle, axis);
}
for (Face &f : this->get_bb().get_faces())
{
f.rotate_around_axis(angle, axis);
}
}
// Utility
void clear_edge_pool()
{
std::sort(this->edge_pool.begin(), this->edge_pool.end());
this->edge_pool.erase(std::unique(this->edge_pool.begin(), this->edge_pool.end()), this->edge_pool.end());
}
void calculate_bb()
{
Vect3 first_v = this->get_faces()[0].get_vertices()[0];
this->bounding_box.set_top_left(first_v);
this->bounding_box.set_bottom_right(first_v);
for (Face &f : faces)
{
std::vector<Vect3> vertices = f.get_vertices();
for (Vect3 v : vertices)
{
bounding_box.expand(v);
}
}
this->bounding_box.create_faces();
}
};