mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-13 15:01:49 +00:00
ObjParser and small libvecn refactor
This commit is contained in:
parent
7536ac2736
commit
859935f3b5
2 changed files with 90 additions and 93 deletions
|
|
@ -10,53 +10,69 @@ class ObjParser : BasicParser<char> {
|
||||||
std::vector<glm::vec2> uvs {{0, 0}};
|
std::vector<glm::vec2> uvs {{0, 0}};
|
||||||
std::vector<glm::vec3> normals {{0, 1, 0}};
|
std::vector<glm::vec3> normals {{0, 1, 0}};
|
||||||
|
|
||||||
// TODO: refactor
|
Vertex parseFaceVertex() {
|
||||||
void parseFace(Mesh& mesh) {
|
auto parseIndex = [&]() -> uint {
|
||||||
std::vector<Vertex> vertices;
|
if (!hasNext() || !is_digit(peekInLine())) {
|
||||||
while (hasNext()) {
|
return 0;
|
||||||
auto c = peekInLine();
|
}
|
||||||
if (c == '\n') {
|
return parseSimpleInt(10);
|
||||||
break;
|
};
|
||||||
} else if (hasNext()) {
|
|
||||||
uint indices[3] {};
|
|
||||||
uint i = 0;
|
|
||||||
do {
|
|
||||||
char next = peekInLine();
|
|
||||||
if (is_digit(next)) {
|
|
||||||
indices[i] = parseSimpleInt(10);
|
|
||||||
if (hasNext() && peekInLine() == '/') {
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
} else if (next == '/') {
|
|
||||||
pos++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (hasNext() && peekInLine() != '\n' && ++i < 3);
|
|
||||||
|
|
||||||
vertices.push_back(Vertex {
|
uint coord = parseIndex();
|
||||||
coords[indices[0]], uvs[indices[1]], normals[indices[2]]});
|
uint uv = 0;
|
||||||
|
uint normal = 0;
|
||||||
|
|
||||||
|
if (hasNext() && peekInLine() == '/') {
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
uv = parseIndex();
|
||||||
|
|
||||||
|
if (hasNext() && peekInLine() == '/') {
|
||||||
|
pos++;
|
||||||
|
normal = parseIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasNext() && peekInLine() != '\n') {
|
|
||||||
skipLine();
|
return Vertex {
|
||||||
}
|
coords[coord],
|
||||||
|
uvs[uv],
|
||||||
|
normals[normal]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void triangulate(const std::vector<Vertex>& vertices, std::vector<Vertex>& output) {
|
||||||
if (vertices.size() >= 3) {
|
if (vertices.size() >= 3) {
|
||||||
for (size_t j = 0; j < vertices.size() - 2; j++) {
|
for (size_t j = 0; j < vertices.size() - 2; j++) {
|
||||||
mesh.vertices.push_back(vertices[0]);
|
output.push_back(vertices[0]);
|
||||||
for (size_t i = 1; i < 3; i++) {
|
for (size_t i = 1; i < 3; i++) {
|
||||||
mesh.vertices.push_back(vertices[i + j]);
|
output.push_back(vertices[i + j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
ObjParser(const std::string_view file, const std::string_view src)
|
void parseFace(Mesh& mesh) {
|
||||||
: BasicParser(file, src) {
|
std::vector<Vertex> vertices;
|
||||||
|
while (hasNext() && peekInLine() != '\n') {
|
||||||
|
vertices.push_back(parseFaceVertex());
|
||||||
|
}
|
||||||
|
triangulate(vertices, mesh.vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Model> parse() {
|
glm::vec3 parseVec3() {
|
||||||
// first iteration - collecting vertex data
|
float x = parseNumber().asNumber();
|
||||||
|
float y = parseNumber().asNumber();
|
||||||
|
float z = parseNumber().asNumber();
|
||||||
|
return glm::vec3 {x, y, z};
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 parseVec2() {
|
||||||
|
float x = parseNumber().asNumber();
|
||||||
|
float y = parseNumber().asNumber();
|
||||||
|
return glm::vec2 {x, y};
|
||||||
|
}
|
||||||
|
|
||||||
|
void collectVertexData() {
|
||||||
while (hasNext()) {
|
while (hasNext()) {
|
||||||
if (peek() == '#') {
|
if (peek() == '#') {
|
||||||
skipLine();
|
skipLine();
|
||||||
|
|
@ -64,27 +80,18 @@ public:
|
||||||
}
|
}
|
||||||
auto cmd = parseName();
|
auto cmd = parseName();
|
||||||
if (cmd == "v") {
|
if (cmd == "v") {
|
||||||
float x = parseNumber().asNumber();
|
coords.emplace_back(parseVec3());
|
||||||
float y = parseNumber().asNumber();
|
|
||||||
float z = parseNumber().asNumber();
|
|
||||||
coords.emplace_back(x, y, z);
|
|
||||||
} else if (cmd == "vt") {
|
} else if (cmd == "vt") {
|
||||||
float u = parseNumber().asNumber();
|
uvs.emplace_back(parseVec2());
|
||||||
float v = parseNumber().asNumber();
|
|
||||||
uvs.emplace_back(u, v);
|
|
||||||
} else if (cmd == "vn") {
|
} else if (cmd == "vn") {
|
||||||
float x = parseNumber().asNumber();
|
normals.emplace_back(parseVec3());
|
||||||
float y = parseNumber().asNumber();
|
|
||||||
float z = parseNumber().asNumber();
|
|
||||||
normals.emplace_back(x, y, z);
|
|
||||||
} else {
|
} else {
|
||||||
skipLine();
|
skipLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// second iteration - building meshes
|
}
|
||||||
reset();
|
|
||||||
|
|
||||||
auto model = std::make_unique<Model>();
|
void buildMeshes(Model& model) {
|
||||||
std::string texture;
|
std::string texture;
|
||||||
while (hasNext()) {
|
while (hasNext()) {
|
||||||
if (peek() != '#' && parseName() == "usemtl") {
|
if (peek() != '#' && parseName() == "usemtl") {
|
||||||
|
|
@ -95,7 +102,7 @@ public:
|
||||||
skipLine();
|
skipLine();
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
Mesh* mesh = &model->addMesh(texture);
|
Mesh* mesh = &model.addMesh(texture);
|
||||||
while (hasNext()) {
|
while (hasNext()) {
|
||||||
if (peek() == '#') {
|
if (peek() == '#') {
|
||||||
skipLine();
|
skipLine();
|
||||||
|
|
@ -105,7 +112,7 @@ public:
|
||||||
if (cmd == "usemtl") {
|
if (cmd == "usemtl") {
|
||||||
skipWhitespace();
|
skipWhitespace();
|
||||||
texture = readUntilEOL();
|
texture = readUntilEOL();
|
||||||
mesh = &model->addMesh(texture);
|
mesh = &model.addMesh(texture);
|
||||||
break;
|
break;
|
||||||
} else if (cmd == "f") {
|
} else if (cmd == "f") {
|
||||||
parseFace(*mesh);
|
parseFace(*mesh);
|
||||||
|
|
@ -113,6 +120,19 @@ public:
|
||||||
skipLine();
|
skipLine();
|
||||||
}
|
}
|
||||||
} while (hasNext());
|
} while (hasNext());
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
ObjParser(const std::string_view file, const std::string_view src)
|
||||||
|
: BasicParser(file, src) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Model> parse() {
|
||||||
|
// first iteration - collecting vertex data
|
||||||
|
collectVertexData();
|
||||||
|
// second iteration - building meshes
|
||||||
|
reset();
|
||||||
|
auto model = std::make_unique<Model>();
|
||||||
|
buildMeshes(*model);
|
||||||
model->clean();
|
model->clean();
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -211,59 +211,36 @@ static int l_tostring(lua::State* L) {
|
||||||
return lua::pushstring(L, ss.str());
|
return lua::pushstring(L, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VECLIB_BASE(dimension) \
|
||||||
|
{"add", lua::wrap<l_binop<dimension, std::plus>>}, \
|
||||||
|
{"sub", lua::wrap<l_binop<dimension, std::minus>>}, \
|
||||||
|
{"mul", lua::wrap<l_binop<dimension, std::multiplies>>}, \
|
||||||
|
{"div", lua::wrap<l_binop<dimension, std::divides>>}, \
|
||||||
|
{"distance", lua::wrap<l_distance<dimension>>}, \
|
||||||
|
{"normalize", lua::wrap<l_unaryop<dimension, glm::normalize>>}, \
|
||||||
|
{"length", lua::wrap<l_scalar_op<dimension, glm::length>>}, \
|
||||||
|
{"tostring", lua::wrap<l_tostring<dimension>>}, \
|
||||||
|
{"abs", lua::wrap<l_unaryop<dimension, glm::abs>>}, \
|
||||||
|
{"round", lua::wrap<l_unaryop<dimension, glm::round>>}, \
|
||||||
|
{"inverse", lua::wrap<l_inverse<dimension>>}, \
|
||||||
|
{"pow", lua::wrap<l_pow<dimension>>}, \
|
||||||
|
{"dot", lua::wrap<l_dot<dimension>>}, \
|
||||||
|
{"mix", lua::wrap<l_mix<dimension>>},
|
||||||
|
|
||||||
const luaL_Reg vec2lib[] = {
|
const luaL_Reg vec2lib[] = {
|
||||||
{"add", lua::wrap<l_binop<2, std::plus>>},
|
VECLIB_BASE(2)
|
||||||
{"sub", lua::wrap<l_binop<2, std::minus>>},
|
|
||||||
{"mul", lua::wrap<l_binop<2, std::multiplies>>},
|
|
||||||
{"div", lua::wrap<l_binop<2, std::divides>>},
|
|
||||||
{"distance", lua::wrap<l_distance<2>>},
|
|
||||||
{"normalize", lua::wrap<l_unaryop<2, glm::normalize>>},
|
|
||||||
{"length", lua::wrap<l_scalar_op<2, glm::length>>},
|
|
||||||
{"tostring", lua::wrap<l_tostring<2>>},
|
|
||||||
{"abs", lua::wrap<l_unaryop<2, glm::abs>>},
|
|
||||||
{"round", lua::wrap<l_unaryop<2, glm::round>>},
|
|
||||||
{"inverse", lua::wrap<l_inverse<2>>},
|
|
||||||
{"pow", lua::wrap<l_pow<2>>},
|
|
||||||
{"dot", lua::wrap<l_dot<2>>},
|
|
||||||
{"angle", lua::wrap<l_vec2_angle>},
|
{"angle", lua::wrap<l_vec2_angle>},
|
||||||
{"mix", lua::wrap<l_mix<2>>},
|
|
||||||
{"rotate", lua::wrap<l_vec2_rotate>},
|
{"rotate", lua::wrap<l_vec2_rotate>},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
const luaL_Reg vec3lib[] = {
|
const luaL_Reg vec3lib[] = {
|
||||||
{"add", lua::wrap<l_binop<3, std::plus>>},
|
VECLIB_BASE(3)
|
||||||
{"sub", lua::wrap<l_binop<3, std::minus>>},
|
|
||||||
{"mul", lua::wrap<l_binop<3, std::multiplies>>},
|
|
||||||
{"div", lua::wrap<l_binop<3, std::divides>>},
|
|
||||||
{"distance", lua::wrap<l_distance<3>>},
|
|
||||||
{"normalize", lua::wrap<l_unaryop<3, glm::normalize>>},
|
|
||||||
{"length", lua::wrap<l_scalar_op<3, glm::length>>},
|
|
||||||
{"tostring", lua::wrap<l_tostring<3>>},
|
|
||||||
{"abs", lua::wrap<l_unaryop<3, glm::abs>>},
|
|
||||||
{"round", lua::wrap<l_unaryop<3, glm::round>>},
|
|
||||||
{"inverse", lua::wrap<l_inverse<3>>},
|
|
||||||
{"pow", lua::wrap<l_pow<3>>},
|
|
||||||
{"dot", lua::wrap<l_dot<3>>},
|
|
||||||
{"spherical_rand", lua::wrap<l_spherical_rand>},
|
{"spherical_rand", lua::wrap<l_spherical_rand>},
|
||||||
{"mix", lua::wrap<l_mix<3>>},
|
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
const luaL_Reg vec4lib[] = {
|
const luaL_Reg vec4lib[] = {
|
||||||
{"add", lua::wrap<l_binop<4, std::plus>>},
|
VECLIB_BASE(4)
|
||||||
{"sub", lua::wrap<l_binop<4, std::minus>>},
|
|
||||||
{"mul", lua::wrap<l_binop<4, std::multiplies>>},
|
|
||||||
{"div", lua::wrap<l_binop<4, std::divides>>},
|
|
||||||
{"distance", lua::wrap<l_distance<4>>},
|
|
||||||
{"normalize", lua::wrap<l_unaryop<4, glm::normalize>>},
|
|
||||||
{"length", lua::wrap<l_scalar_op<4, glm::length>>},
|
|
||||||
{"tostring", lua::wrap<l_tostring<4>>},
|
|
||||||
{"abs", lua::wrap<l_unaryop<4, glm::abs>>},
|
|
||||||
{"round", lua::wrap<l_unaryop<4, glm::round>>},
|
|
||||||
{"inverse", lua::wrap<l_inverse<4>>},
|
|
||||||
{"pow", lua::wrap<l_pow<4>>},
|
|
||||||
{"dot", lua::wrap<l_dot<4>>},
|
|
||||||
{"mix", lua::wrap<l_mix<4>>},
|
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue