File MeshData.cpp
File List > render > MeshData.cpp
Go to the documentation of this file
#include "MeshData.h"
#include "macros.h"
#include "structs.h"
#include "operator.h"
std::string MeshData::obj_file_root = "res/obj/";
#include <fstream>
#include <sstream>
#include <algorithm>
#include <execution>
inline MeshData::VertexIdx Split(std::string_view in) {
std::string out[3] = { "","","" };
int count = 0;
for (int i = 0; i < in.length(); i++)
{
if (in[i] == '/') {
count++;
continue;
}
else {
out[count] += in[i];
}
}
MeshData::VertexIdx res;
res.pos = 3 * std::stoi(out[0]) - 3;
res.uv = 2 * std::stoi(out[1]) - 2;
res.norm = 3 * std::stoi(out[2]) - 3;
return res;
}
inline MeshData::ByteArray ReadObj(const std::string& path, bool is_smooth = true) {
Timer timer("Load OBJ");
MeshData::ByteArray result;
std::vector<std::vector<int>> vertIndex;
std::vector<float> tempdata[4];
std::fstream obj;
obj.open(path);
std::string a = "";
std::string last = "";
bool is_face = true;
int vert_count = 0;
//timer.Tick();
//Timer timer2;
while (!obj.eof())
{
getline(obj, a);
//if (last != a.substr(0, 2)) {
last = a.substr(0, 2);
std::istringstream str(a);
if (last == "v ")
{
while (str >> last)
{
if (last == "v")continue;
tempdata[0].emplace_back(float(atof(last.c_str())));
}
result.count[0]++;
}
else if (last == "vt")
{
while (str >> last)
{
if (last == "vt")continue;
tempdata[1].emplace_back(float(atof(last.c_str())));
}
result.count[1]++;
}
else if (last == "vn")
{
while (str >> last)
{
if (last == "vn")continue;
tempdata[2].emplace_back(float(atof(last.c_str())));
}
result.count[2]++;
}
else if (last == "f ")
{
if (is_face)
{
//init
is_face = false;
vertIndex.resize(result.count[0] * 4);
}
while (str >> last)
{
if (last == "f")continue;
MeshData::VertexIdx face = Split(last);
result.data_array.emplace_back(tempdata[0][face.pos + 0]);
result.data_array.emplace_back(tempdata[0][face.pos + 1]);
result.data_array.emplace_back(tempdata[0][face.pos + 2]);
result.data_array.emplace_back(tempdata[1][face.uv + 0]);
result.data_array.emplace_back(tempdata[1][face.uv + 1]);
result.data_array.emplace_back(tempdata[2][face.norm + 0]);
result.data_array.emplace_back(tempdata[2][face.norm + 1]);
result.data_array.emplace_back(tempdata[2][face.norm + 2]);
result.data_array.emplace_back(0.0f);
result.data_array.emplace_back(0.0f);
result.data_array.emplace_back(0.0f);
vertIndex[(face.pos) / 3].push_back(result.count[3] * 3 + vert_count);
vert_count++;
if (vert_count >= 3)
vert_count = 0;
}
result.count[3]++;
}
else if (last == "o ") {
while (str >> last)
{
if (last == "o")continue;
result.name += last.c_str();
}
}
}
if (is_smooth)
{
std::for_each(std::execution::par_unseq, vertIndex.begin(), vertIndex.end(), [&](std::vector<int>& indices) {
if (indices.empty())
return;
float SMX = 0.0f, SMY = 0.0f, SMZ = 0.0f;
for (int j = 0; j < indices.size(); j++)
{
SMX += result.data_array[indices[j] * 11 + 5] / indices.size();
SMY += result.data_array[indices[j] * 11 + 6] / indices.size();
SMZ += result.data_array[indices[j] * 11 + 7] / indices.size();
}
for (int j = 0; j < indices.size(); j++)
{
result.data_array[indices[j] * 11 + 8] = SMX;
result.data_array[indices[j] * 11 + 9] = SMY;
result.data_array[indices[j] * 11 + 10] = SMZ;
}
});
}
else {
std::for_each(std::execution::par_unseq, vertIndex.begin(), vertIndex.end(), [&](std::vector<int>& indices) {
if (indices.empty())
return;
for (int j = 0; j < indices.size(); j++)
{
result.data_array[indices[j] * 11 + 8] = result.data_array[indices[j] * 11 + 5];
result.data_array[indices[j] * 11 + 9] = result.data_array[indices[j] * 11 + 6];
result.data_array[indices[j] * 11 + 10] = result.data_array[indices[j] * 11 + 7];
}
});
}
//timer.Tick();
for (int i = 0; i < result.count[0]; i++)
{
glm::vec3 pos = { tempdata[0][3 * i + 0] , tempdata[0][3 * i + 1] ,tempdata[0][3 * i + 2] };
result.center += pos;
}
result.center /= result.count[0];
return result;
}
MeshData::MeshData()
{}
void MeshData::LoadObj(const std::string& path)
{
std::string path_ = path.find(MeshData::obj_file_root) == std::string::npos ? MeshData::obj_file_root + path : path;
me_read = ReadObj(path_);
//std::cout << VertData[100] << std::endl;
me_vertBuffer = VertexBuffer(me_read.data_array);
BufferLayout layout;
layout.Push<float>(3); //3D position
layout.Push<float>(2); //UV
layout.Push<float>(3); //Normal
layout.Push<float>(3); //Smooth Normal
me_vertArry.AddBuffer(me_vertBuffer, layout);
/*o_verts.Unbind();*/
const int size = me_read.count[3] * 3;
std::vector<GLuint> indexArray = std::vector<GLuint>(size);
std::iota(indexArray.begin(), indexArray.end(), 0);
me_index = IndexBuffer(indexArray.data(), indexArray.size() * sizeof(GLuint));
}
void MeshData::RenderObjProxy() const
{
me_vertArry.Bind();
me_index.Bind();
glDrawElements(GL_TRIANGLES, me_index.Count(), GL_UNSIGNED_INT, NULL);
me_index.Unbind();
me_vertArry.Unbind();
}
void MeshData::BindVBO(GLuint slot) const
{
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, me_vertBuffer.GetID());
}
glm::vec3 MeshData::GetMeshCenter() const
{
return me_read.center;
}
std::string MeshData::GetMeshName() const
{
return me_read.name;
}
std::unordered_map<std::string, MeshLib::MeshResource> MeshLib::mesh_list = {};
MeshLib::MeshResource MeshLib::Square = nullptr;
MeshLib::MeshLib()
{
}
MeshLib::~MeshLib()
{
}
void MeshLib::MeshLibInit()
{
MeshLib::Square = LoadMesh("square.obj");
}
MeshLib::MeshResource MeshLib::LoadMesh(const std::string path)
{
if (mesh_list.find(path) != mesh_list.end())
return mesh_list[path];
MeshLib::MeshResource mesh = std::make_shared<MeshData>();
mesh->LoadObj(path);
return mesh;
}
void MeshLib::ToGeoCenter(MeshResource _tar)
{
_tar->me_vertBuffer.Bind();
GLfloat* pData = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
if (pData == nullptr)
return;
for (int i = 0; i < _tar->me_read.data_array.size(); i += _tar->me_vertArry.GetStride()) {
LOOP_N(3, j)
pData[i + j] -= _tar->me_read.center[j];
}
glUnmapBuffer(GL_ARRAY_BUFFER);
_tar->me_read.center = glm::vec3{ 0 };
DEBUG("Done");
}