Files
SDL3CPlusPlus/src/services/impl/mesh_service.cpp
johndoe6345789 19c369aac1 Refactor script services to improve Lua integration and logging
- Updated MeshService to use MeshPayload directly instead of script::MeshPayload.
- Enhanced SceneScriptService with detailed logging and error handling for Lua interactions.
- Introduced ILogger dependency in SceneScriptService and ShaderScriptService for better traceability.
- Implemented Lua state management in ScriptEngineService, allowing direct access to Lua functions.
- Added new types for mesh and scene management, including MeshPayload and SceneObject.
- Refactored shader loading logic in ShaderScriptService to utilize Lua for shader path retrieval.
- Created GuiInputSnapshot and GuiCommand structures for GUI input handling.
- Updated input and GUI script services to use new types and improved interfaces.
- Enhanced test_cube_script to validate new service implementations and Lua interactions.
2026-01-04 23:46:46 +00:00

146 lines
4.6 KiB
C++

#include "mesh_service.hpp"
#include <utility>
#include <assimp/Importer.hpp>
#include <assimp/material.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <filesystem>
#include <lua.hpp>
#include <system_error>
namespace sdl3cpp::services::impl {
MeshService::MeshService(std::shared_ptr<IConfigService> configService)
: configService_(std::move(configService)) {
}
bool MeshService::LoadFromFile(const std::string& requestedPath,
MeshPayload& outPayload,
std::string& outError) {
if (!configService_) {
outError = "Config service not available";
return false;
}
std::filesystem::path resolved(requestedPath);
if (!resolved.is_absolute()) {
resolved = configService_->GetScriptPath().parent_path() / resolved;
}
std::error_code ec;
resolved = std::filesystem::weakly_canonical(resolved, ec);
if (ec) {
outError = "Failed to resolve mesh path: " + ec.message();
return false;
}
if (!std::filesystem::exists(resolved)) {
outError = "Mesh file not found: " + resolved.string();
return false;
}
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(
resolved.string(),
aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_PreTransformVertices);
if (!scene) {
outError = importer.GetErrorString() ? importer.GetErrorString() : "Assimp failed to load mesh";
return false;
}
if (scene->mNumMeshes == 0) {
outError = "Scene contains no meshes";
return false;
}
const aiMesh* mesh = scene->mMeshes[0];
if (!mesh->mNumVertices) {
outError = "Mesh contains no vertices";
return false;
}
outPayload.positions.clear();
outPayload.colors.clear();
outPayload.indices.clear();
outPayload.positions.reserve(mesh->mNumVertices);
outPayload.colors.reserve(mesh->mNumVertices);
outPayload.indices.reserve(mesh->mNumFaces * 3);
aiColor3D defaultColor(0.6f, 0.8f, 1.0f);
aiColor3D materialColor = defaultColor;
if (mesh->mMaterialIndex < scene->mNumMaterials) {
const aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
aiColor4D diffuse;
if (material && material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse) == AI_SUCCESS) {
materialColor = aiColor3D(diffuse.r, diffuse.g, diffuse.b);
}
}
for (unsigned i = 0; i < mesh->mNumVertices; ++i) {
const aiVector3D& vertex = mesh->mVertices[i];
outPayload.positions.push_back({vertex.x, vertex.y, vertex.z});
aiColor3D color = materialColor;
if (mesh->HasVertexColors(0) && mesh->mColors[0]) {
const aiColor4D& vertexColor = mesh->mColors[0][i];
color = aiColor3D(vertexColor.r, vertexColor.g, vertexColor.b);
}
outPayload.colors.push_back({color.r, color.g, color.b});
}
for (unsigned faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) {
const aiFace& face = mesh->mFaces[faceIndex];
if (face.mNumIndices != 3) {
continue;
}
outPayload.indices.push_back(face.mIndices[0]);
outPayload.indices.push_back(face.mIndices[1]);
outPayload.indices.push_back(face.mIndices[2]);
}
if (outPayload.indices.empty()) {
outError = "Mesh contains no triangle faces";
return false;
}
return true;
}
void MeshService::PushMeshToLua(lua_State* L, const MeshPayload& payload) {
lua_newtable(L);
lua_newtable(L);
for (size_t vertexIndex = 0; vertexIndex < payload.positions.size(); ++vertexIndex) {
lua_newtable(L);
lua_newtable(L);
for (int component = 0; component < 3; ++component) {
lua_pushnumber(L, payload.positions[vertexIndex][component]);
lua_rawseti(L, -2, component + 1);
}
lua_setfield(L, -2, "position");
lua_newtable(L);
for (int component = 0; component < 3; ++component) {
lua_pushnumber(L, payload.colors[vertexIndex][component]);
lua_rawseti(L, -2, component + 1);
}
lua_setfield(L, -2, "color");
lua_rawseti(L, -2, static_cast<int>(vertexIndex + 1));
}
lua_setfield(L, -2, "vertices");
lua_newtable(L);
for (size_t index = 0; index < payload.indices.size(); ++index) {
lua_pushinteger(L, static_cast<lua_Integer>(payload.indices[index]) + 1);
lua_rawseti(L, -2, static_cast<int>(index + 1));
}
lua_setfield(L, -2, "indices");
}
} // namespace sdl3cpp::services::impl