obj laoder

v1
Brett 2024-01-11 15:51:00 -05:00
parent 60ec2051d8
commit a4f0b1e3d4
2 changed files with 76 additions and 24 deletions

View File

@ -31,6 +31,7 @@ namespace blt::gfx
typedef blt::vec3f vertex_t; typedef blt::vec3f vertex_t;
typedef blt::vec2f uv_t; typedef blt::vec2f uv_t;
typedef blt::vec3f normal_t; typedef blt::vec3f normal_t;
typedef blt::vec3f color_t;
class model_data class model_data
{ {
@ -85,31 +86,55 @@ namespace blt::gfx
std::int32_t v[4]; std::int32_t v[4];
}; };
struct material_t
{
std::string material_name;
color_t ambient;
color_t diffuse;
color_t specular;
float specular_exponent = 0.0f;
float transparency = 1.0f;
color_t transmission_filter_color{1, 1, 1};
std::string texture_ambient;
std::string texture_diffuse;
std::string map_spec_color;
std::string map_spec_highlight;
std::string map_bump;
std::string map_displacement;
};
struct object_data struct object_data
{ {
std::string object_name; std::vector<std::string> object_names;
std::string material;
std::vector<triangle_t> indices; std::vector<triangle_t> indices;
}; };
class obj_objects_t class obj_model_t
{ {
private: private:
std::vector<constructed_vertex_t> vertex_data_; std::vector<constructed_vertex_t> vertex_data_;
std::vector<object_data> objects_; std::vector<object_data> objects_;
HASHMAP<std::string, material_t> materials_;
public: public:
obj_objects_t(std::vector<constructed_vertex_t>&& vertex_data, std::vector<object_data>&& objects): obj_model_t(std::vector<constructed_vertex_t>&& vertex_data, std::vector<object_data>&& objects, HASHMAP<std::string, material_t>&& mats):
vertex_data_(vertex_data), objects_(objects) vertex_data_(vertex_data), objects_(objects), materials_(mats)
{} {}
inline const std::vector<constructed_vertex_t>& vertex_data() inline const auto& vertex_data()
{ {
return vertex_data_; return vertex_data_;
}; };
inline const std::vector<object_data>& objects() inline const auto& objects()
{ {
return objects_; return objects_;
}; };
inline const auto& materials()
{
return materials_;
}
}; };
class char_tokenizer; class char_tokenizer;
@ -126,6 +151,9 @@ namespace blt::gfx
std::vector<constructed_vertex_t> vertex_data; std::vector<constructed_vertex_t> vertex_data;
object_data current_object; object_data current_object;
std::vector<object_data> data; std::vector<object_data> data;
HASHMAP<std::string, material_t> materials;
size_t current_line = 0;
private: private:
bool handle_vertex_and_normals(float x, float y, float z, char type); bool handle_vertex_and_normals(float x, float y, float z, char type);
@ -136,10 +164,10 @@ namespace blt::gfx
void handle_face_vertex(const std::vector<std::string>& face_list, std::int32_t* arr); void handle_face_vertex(const std::vector<std::string>& face_list, std::int32_t* arr);
public: public:
obj_objects_t parseFile(std::string_view file); obj_model_t parseFile(std::string_view file);
}; };
obj_objects_t quick_load(std::string_view file); obj_model_t quick_load(std::string_view file);
} }

View File

@ -15,14 +15,18 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#define BLT_DISABLE_TRACE
#define BLT_DISABLE_DEBUG
#include <blt/parse/obj_loader.h> #include <blt/parse/obj_loader.h>
#include <blt/std/loader.h> #include <blt/std/loader.h>
#include <blt/std/string.h> #include <blt/std/string.h>
#include <blt/std/logging.h>
#include <cctype> #include <cctype>
#include <charconv> #include <charconv>
#include "blt/std/assert.h" #include "blt/std/assert.h"
#include "blt/std/utility.h" #include "blt/std/utility.h"
#include <blt/std/logging.h>
namespace blt::gfx namespace blt::gfx
{ {
@ -86,6 +90,7 @@ namespace blt::gfx
auto elements = blt::string::split(std::string(tokenizer.read_fully()), " "); auto elements = blt::string::split(std::string(tokenizer.read_fully()), " ");
BLT_ASSERT(elements.size() >= 2 && "Current line doesn't have enough arguments to process!"); BLT_ASSERT(elements.size() >= 2 && "Current line doesn't have enough arguments to process!");
float x = get(elements[0]), y = get(elements[1]); float x = get(elements[0]), y = get(elements[1]);
BLT_DEBUG_STREAM << "Loaded value of (" << x << ", " << y << ")";
if (elements.size() < 3) if (elements.size() < 3)
{ {
if (type == 't') if (type == 't')
@ -95,9 +100,11 @@ namespace blt::gfx
} else } else
{ {
float z = get(elements[2]); float z = get(elements[2]);
BLT_DEBUG_STREAM << " with z: " << z;
if (!handle_vertex_and_normals(x, y, z, type)) if (!handle_vertex_and_normals(x, y, z, type))
BLT_ERROR("Unable to parse line '%s' type '%c' not recognized", std::string(tokenizer.read_fully()).c_str(), type); BLT_ERROR("Unable to parse line '%s' type '%c' not recognized", std::string(tokenizer.read_fully()).c_str(), type);
} }
BLT_DEBUG_STREAM << "\n";
} }
bool obj_loader::handle_vertex_and_normals(float x, float y, float z, char type) bool obj_loader::handle_vertex_and_normals(float x, float y, float z, char type)
@ -113,16 +120,18 @@ namespace blt::gfx
return true; return true;
} }
obj_objects_t quick_load(std::string_view file) obj_model_t quick_load(std::string_view file)
{ {
return obj_loader().parseFile(file); return obj_loader().parseFile(file);
} }
obj_objects_t obj_loader::parseFile(std::string_view file) obj_model_t obj_loader::parseFile(std::string_view file)
{ {
auto lines = blt::fs::getLinesFromFile(std::string(file)); auto lines = blt::fs::getLinesFromFile(std::string(file));
for (const auto& line : lines) for (auto line_e : blt::enumerate(lines))
{ {
auto& line = line_e.second;
current_line = line_e.first;
char_tokenizer token(line); char_tokenizer token(line);
if (!token.has_next() || token.read_fully().empty()) if (!token.has_next() || token.read_fully().empty())
continue; continue;
@ -138,29 +147,35 @@ namespace blt::gfx
break; break;
case 'o': case 'o':
{ {
if (!current_object.indices.empty()) current_object.object_names.emplace_back(token.read_fully());
data.push_back(current_object); BLT_TRACE("Setting object '%s'", std::string(current_object.object_name).c_str());
current_object = {};
current_object.object_name = token.read_fully();
break; break;
} }
case 'm': case 'm':
{ {
BLT_TRACE("Material '%s' needs to be loaded!", std::string(token.read_fully()).c_str()); while (token.has_next() && token.advance() != ' ')
{}
BLT_WARN("Material '%s' needs to be loaded!", std::string(token.read_fully()).c_str());
break; break;
} }
case 'u': case 'u':
{ {
BLT_TRACE("Using material '%s'", std::string(token.read_fully()).c_str()); if (!current_object.indices.empty())
data.push_back(current_object);
current_object = {};
while (token.has_next() && token.advance() != ' ')
{}
current_object.material = token.read_fully();
//BLT_WARN("Using material '%s'", std::string(token.read_fully()).c_str());
break; break;
} }
case 's': case 's':
BLT_TRACE("Using shading: %s", std::string(token.read_fully()).c_str()); //BLT_WARN("Using shading: %s", std::string(token.read_fully()).c_str());
break; break;
} }
} }
data.push_back(current_object); data.push_back(current_object);
return {std::move(vertex_data), std::move(data)}; return {std::move(vertex_data), std::move(data), std::move(materials)};
} }
void obj_loader::parse_face(char_tokenizer& tokenizer) void obj_loader::parse_face(char_tokenizer& tokenizer)
@ -187,7 +202,7 @@ namespace blt::gfx
current_object.indices.push_back(t1); current_object.indices.push_back(t1);
current_object.indices.push_back(t2); current_object.indices.push_back(t2);
} else } else
BLT_WARN("Unsupported vertex count! %d", faces.size()); BLT_WARN("Unsupported face vertex count of %d on line %d!", faces.size(), current_line);
} }
void obj_loader::handle_face_vertex(const std::vector<std::string>& face_list, int32_t* arr) void obj_loader::handle_face_vertex(const std::vector<std::string>& face_list, int32_t* arr)
@ -197,21 +212,30 @@ namespace blt::gfx
auto indices = blt::string::split(pair.second, '/'); auto indices = blt::string::split(pair.second, '/');
BLT_ASSERT(indices.size() == 3 && "Must have vertex, uv, and normal indices!!"); BLT_ASSERT(indices.size() == 3 && "Must have vertex, uv, and normal indices!!");
auto vi = get<std::int32_t>(indices[0]); auto vi = get<std::int32_t>(indices[0]) - 1;
auto ui = get<std::int32_t>(indices[1]); auto ui = get<std::int32_t>(indices[1]) - 1;
auto ni = get<std::int32_t>(indices[2]); auto ni = get<std::int32_t>(indices[2]) - 1;
BLT_DEBUG("Found vertex: %d, UV: %d, and normal: %d", vi, ui, ni);
face_t face{vi, ui, ni}; face_t face{vi, ui, ni};
auto loc = vertex_map.find(face); auto loc = vertex_map.find(face);
if (loc == vertex_map.end()) if (loc == vertex_map.end())
{ {
BLT_DEBUG("DID NOT FIND FACE!");
auto index = static_cast<std::int32_t>(vertex_data.size()); auto index = static_cast<std::int32_t>(vertex_data.size());
vertex_data.push_back({vertices[vi], uvs[ui], normals[ni]}); vertex_data.push_back({vertices[vi], uvs[ui], normals[ni]});
BLT_DEBUG("Vertex: (%f, %f, %f), UV: (%f, %f), Normal: (%f, %f, %f)", vertices[vi].x(), vertices[vi].y(), vertices[vi].z(),
uvs[ui].x(), uvs[ui].y(), normals[ni].x(), normals[ni].y(), normals[ni].z());
vertex_map.insert({face, index}); vertex_map.insert({face, index});
arr[pair.first] = index; arr[pair.first] = index;
} else } else
{ {
BLT_TRACE("Using cached data; %d; map size: %d", loc->second, vertex_data.size());
const auto& d = vertex_data[loc->second];
BLT_TRACE("Vertex: (%f, %f, %f), UV: (%f, %f), Normal: (%f, %f, %f)", d.vertex.x(), d.vertex.y(), d.vertex.z(),
d.uv.x(), d.uv.y(), d.normal.x(), d.normal.y(), d.normal.z());
arr[pair.first] = loc->second; arr[pair.first] = loc->second;
} }
} }