Files
openglplayground/objectParser.cc

282 lines
11 KiB
C++

#include <iostream>
#include <cassert>
#include <vector>
#include <tuple>
#include <map>
#include <tr1/functional>
#include <obj.hpp>
#include "objectParser.hh"
using namespace obj;
using std::tr1::placeholders::_1;
using std::tr1::placeholders::_2;
using std::tr1::placeholders::_3;
using std::tr1::placeholders::_4;
class ObjectParser {
private:
void texture_vertex_callback(obj::float_type u, obj::float_type v)
{
if ((u > 1.0f) || (u < 0.0f))
std::cout << "Warning: Clamping texture coordinate U to [0.0, 1.0]" << std::endl;
uint16_t c_u = static_cast<uint16_t>(fminf(1.0f, fmaxf(0.0f, u))*65535.0);
if ((v > 1.0f) || (v < 0.0f))
std::cout << "Warning: Clamping texture coordinate V to [0.0, 1.0]" << std::endl;
uint16_t c_v = static_cast<uint16_t>(fminf(1.0f, fmaxf(0.0f, v))*65535.0);
_texCoords.emplace_back(c_u, c_v);
std::cout << "vt " << c_u << " " << c_v << "\n";
}
void geometric_vertex_callback(obj::float_type x, obj::float_type y, obj::float_type z)
{
_vertices.emplace_back(x, y, z);
std::cout << "v " << x << " " << y << " " << z << "\n";
}
void vertex_normal_callback(obj::float_type x, obj::float_type y, obj::float_type z)
{
union {
struct {
signed :2;
signed z:10;
signed y:10;
signed x:10;
} bits;
uint32_t all;
} pack_10;
if ((x > 1.0f) || (x < -1.0f))
std::cout << "Warning: Clamping normal X to [-1.0, 1.0]" << std::endl;
pack_10.bits.x = static_cast<int>(fminf(1.0f, fmaxf(-1.0f, x))*511.0);
if ((y > 1.0f) || (y < -1.0f))
std::cout << "Warning: Clamping normal Y to [-1.0, 1.0]" << std::endl;
pack_10.bits.y = static_cast<int>(fminf(1.0f, fmaxf(-1.0f, y))*511.0);
if ((z > 1.0f) || (z < -1.0f))
std::cout << "Warning: Clamping normal Z to [-1.0, 1.0]" << std::endl;
pack_10.bits.z = static_cast<int>(fminf(1.0f, fmaxf(-1.0f, z))*511.0);
_normals.push_back(pack_10.all);
std::cout << "vn " << pack_10.bits.x << " " << pack_10.bits.y << " " << pack_10.bits.z << "\n";
}
void triangular_face_geometric_vertices_callback(index_type a, index_type b, index_type c)
{
}
size_t _find_vertex_tc_pair(index_2_tuple_type const& a)
{
auto pair_it = _vertex_tc_pairs_map.find(std::tuple<std::size_t, std::size_t>(std::tr1::get<0>(a), std::tr1::get<1>(a)));
size_t pair_pos;
if (pair_it != _vertex_tc_pairs_map.end())
pair_pos = pair_it->second;
else {
_vertex_tc_pairs.emplace_back(std::get<0>(_vertices[std::tr1::get<0>(a)-1]),
std::get<1>(_vertices[std::tr1::get<0>(a)-1]),
std::get<2>(_vertices[std::tr1::get<0>(a)-1]),
std::get<0>(_texCoords[std::tr1::get<1>(a)-1]),
std::get<1>(_texCoords[std::tr1::get<1>(a)-1]));
pair_pos = _vertex_tc_pairs.size()-1;
_vertex_tc_pairs_map.emplace(std::tuple<std::size_t, std::size_t>(std::tr1::get<0>(a), std::tr1::get<1>(a)),
pair_pos);
}
return pair_pos;
}
void triangular_face_geometric_vertices_texture_vertices_callback(index_2_tuple_type a, index_2_tuple_type b, index_2_tuple_type c)
{
if ((_vertices.size() < std::tr1::get<0>(a)) ||
(_vertices.size() < std::tr1::get<0>(b)) ||
(_vertices.size() < std::tr1::get<0>(c)))
throw ParseException("Vertex Index out of range");
if ((_texCoords.size() < std::tr1::get<1>(a)) ||
(_texCoords.size() < std::tr1::get<1>(b)) ||
(_texCoords.size() < std::tr1::get<1>(c)))
throw ParseException("Texture Coordinate Index out of range");
std::cout << "f (" << std::tr1::get<0>(a) << ", " << std::tr1::get<1>(a) << ")" <<
" (" << std::tr1::get<0>(b) << ", " << std::tr1::get<1>(b) << ")" <<
" (" << std::tr1::get<0>(c) << ", " << std::tr1::get<1>(c) << ")\n";
size_t a_pos = _find_vertex_tc_pair(a);
size_t b_pos = _find_vertex_tc_pair(b);
size_t c_pos = _find_vertex_tc_pair(c);
_faces.emplace_back(a_pos, b_pos, c_pos);
std::cout << "\t [" << a_pos << ", " << b_pos << ", " << c_pos << "]\n";
}
void triangular_face_geometric_vertices_vertex_normals_callback(index_2_tuple_type a, index_2_tuple_type b, index_2_tuple_type c)
{
}
void triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback(index_3_tuple_type a, index_3_tuple_type b,
index_3_tuple_type c)
{
}
void quadrilateral_face_geometric_vertices_callback(index_type a, index_type b, index_type c, index_type d)
{
assert(false);
}
void quadrilateral_face_geometric_vertices_texture_vertices_callback(index_2_tuple_type a, index_2_tuple_type b,
index_2_tuple_type c, index_2_tuple_type d)
{
assert(false);
}
void quadrilateral_face_geometric_vertices_vertex_normals_callback(index_2_tuple_type a, index_2_tuple_type b,
index_2_tuple_type c, index_2_tuple_type d)
{
assert(false);
}
void quadrilateral_face_geometric_vertices_texture_vertices_vertex_normals_callback(index_3_tuple_type a, index_3_tuple_type b,
index_3_tuple_type c, index_3_tuple_type d)
{
assert(false);
}
void polygonal_face_geometric_vertices_begin_callback(index_type a, index_type b, index_type c)
{
assert(false);
}
void polygonal_face_geometric_vertices_vertex_callback(index_type a)
{
assert(false);
}
void polygonal_face_geometric_vertices_end_callback()
{
assert(false);
}
void polygonal_face_geometric_vertices_texture_vertices_begin_callback(index_2_tuple_type a, index_2_tuple_type b,
index_2_tuple_type c)
{
assert(false);
}
void polygonal_face_geometric_vertices_texture_vertices_vertex_callback(index_2_tuple_type a)
{
assert(false);
}
void polygonal_face_geometric_vertices_texture_vertices_end_callback()
{
assert(false);
}
void polygonal_face_geometric_vertices_vertex_normals_begin_callback(index_2_tuple_type a, index_2_tuple_type b,
index_2_tuple_type c)
{
assert(false);
}
void polygonal_face_geometric_vertices_vertex_normals_vertex_callback(index_2_tuple_type a)
{
assert(false);
}
void polygonal_face_geometric_vertices_vertex_normals_end_callback()
{
assert(false);
}
void polygonal_face_geometric_vertices_texture_vertices_vertex_normals_begin_callback(index_3_tuple_type a, index_3_tuple_type b,
index_3_tuple_type c)
{
assert(false);
}
void polygonal_face_geometric_vertices_texture_vertices_vertex_normals_vertex_callback(index_3_tuple_type a)
{
assert(false);
}
void polygonal_face_geometric_vertices_texture_vertices_vertex_normals_end_callback()
{
assert(false);
}
std::vector<std::tuple<float, float, float> > _vertices;
std::vector<std::tuple<uint16_t, uint16_t> > _texCoords;
std::vector<uint32_t> _normals;
std::map<std::tuple<std::size_t, std::size_t>, std::size_t > _vertex_tc_pairs_map;
std::vector<std::tuple<float, float, float, uint16_t, uint16_t> > _vertex_tc_pairs;
std::vector<std::tuple<std::size_t, std::size_t, std::size_t> > _faces;
public:
ObjectParser() {
}
~ObjectParser() {
}
void parse(std::string const& filename)
{
obj::obj_parser obj_parser(obj::obj_parser::triangulate_faces | obj::obj_parser::translate_negative_indices);
obj_parser.geometric_vertex_callback(std::tr1::bind(&ObjectParser::geometric_vertex_callback, this, _1, _2, _3));
obj_parser.texture_vertex_callback(std::tr1::bind(&ObjectParser::texture_vertex_callback, this, _1, _2));
obj_parser.vertex_normal_callback(std::tr1::bind(&ObjectParser::vertex_normal_callback, this, _1, _2, _3));
obj_parser.face_callbacks
(std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_texture_vertices_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_vertex_normals_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_callback, this, _1, _2, _3, _4),
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_texture_vertices_callback, this, _1, _2, _3, _4),
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_vertex_normals_callback, this, _1, _2, _3, _4),
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_texture_vertices_vertex_normals_callback, this, _1, _2, _3, _4),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_begin_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_callback, this, _1),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_end_callback, this),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_begin_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_callback, this, _1),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_end_callback, this),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_normals_begin_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_normals_vertex_callback, this, _1),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_normals_end_callback, this),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_normals_begin_callback, this, _1, _2, _3),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_normals_vertex_callback, this, _1),
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_normals_end_callback, this));
obj_parser.parse(filename);
}
std::vector<objVertexAttribs> buildVA()
{
std::vector<objVertexAttribs> ret;
for (auto const& ent : _vertex_tc_pairs) {
objVertexAttribs tmp;
tmp.vertex[0] = std::get<0>(ent);
tmp.vertex[1] = std::get<1>(ent);
tmp.vertex[2] = std::get<2>(ent);
tmp.texCoords[0] = std::get<3>(ent);
tmp.texCoords[1] = std::get<4>(ent);
ret.push_back(tmp);
}
return ret;
}
std::vector<uint16_t> buildIndices() const
{
std::vector<uint16_t> ret;
for (auto const& ent : _faces) {
ret.push_back(std::get<0>(ent));
ret.push_back(std::get<1>(ent));
ret.push_back(std::get<2>(ent));
}
return ret;
}
};
std::tuple<std::vector<objVertexAttribs>, std::vector<uint16_t> > readObject(std::string const& filename)
{
ObjectParser parser;
parser.parse(filename);
return std::tuple<std::vector<objVertexAttribs>, std::vector<uint16_t> >(parser.buildVA(), parser.buildIndices());
}