Model optimization

This commit is contained in:
Vladislav Khorev committed 2026-05-01 21:47:54 +03:00
1 parent be6a8cca9e
commit d24748df1e
5 files changed
+244 -10

No files matched your search

+85
View File
@@ -10,8 +10,22 @@
namespace ZL
{
static std::unordered_map<std::string, VertexDataStruct> s_meshCache;
static std::string CacheKey(const std::string& fileName)
{
if (fileName.size() > 4 && fileName.compare(fileName.size() - 4, 4, ".bin") == 0)
return fileName.substr(0, fileName.size() - 4);
return fileName;
}
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName)
{
std::string key = CacheKey(fileName);
auto it = s_meshCache.find(key);
if (it != s_meshCache.end())
return it->second;
VertexDataStruct result;
std::istringstream f;
@@ -181,10 +195,81 @@ namespace ZL
std::cout << "Model loaded: " << numberVertices << " verts, " << numberTriangles << " tris." << std::endl;
s_meshCache[key] = result;
return result;
}
VertexDataStruct LoadModelFromBinFile(const std::string& fileName, const std::string& ZIPFileName)
{
std::string key = CacheKey(fileName);
auto it = s_meshCache.find(key);
if (it != s_meshCache.end())
return it->second;
std::vector<char> fileData = !ZIPFileName.empty()
? readFileFromZIP(fileName, ZIPFileName)
: readFile(fileName);
if (fileData.size() < 16)
throw std::runtime_error("Binary mesh file is too short: " + fileName);
const char* ptr = fileData.data();
if (ptr[0] != 'B' || ptr[1] != 'S' || ptr[2] != 'M' || ptr[3] != 'F')
throw std::runtime_error("Invalid magic bytes in binary mesh file: " + fileName);
ptr += 4;
uint32_t version = *reinterpret_cast<const uint32_t*>(ptr); ptr += 4;
if (version != 1)
throw std::runtime_error("Unsupported binary mesh version " + std::to_string(version) + ": " + fileName);
uint32_t numVertices = *reinterpret_cast<const uint32_t*>(ptr); ptr += 4;
uint32_t numTriangles = *reinterpret_cast<const uint32_t*>(ptr); ptr += 4;
const size_t expectedSize = 16
+ static_cast<size_t>(numVertices) * 8 * sizeof(float)
+ static_cast<size_t>(numTriangles) * 3 * sizeof(uint32_t);
if (fileData.size() < expectedSize)
throw std::runtime_error("Binary mesh file is truncated: " + fileName);
std::vector<Vector3f> positions(numVertices);
std::vector<Vector3f> normals(numVertices);
std::vector<Vector2f> uvs(numVertices);
for (uint32_t i = 0; i < numVertices; ++i)
{
positions[i](0) = *reinterpret_cast<const float*>(ptr); ptr += 4;
positions[i](1) = *reinterpret_cast<const float*>(ptr); ptr += 4;
positions[i](2) = *reinterpret_cast<const float*>(ptr); ptr += 4;
normals[i](0) = *reinterpret_cast<const float*>(ptr); ptr += 4;
normals[i](1) = *reinterpret_cast<const float*>(ptr); ptr += 4;
normals[i](2) = *reinterpret_cast<const float*>(ptr); ptr += 4;
uvs[i](0) = *reinterpret_cast<const float*>(ptr); ptr += 4;
uvs[i](1) = *reinterpret_cast<const float*>(ptr); ptr += 4;
}
VertexDataStruct result;
result.PositionData.reserve(numTriangles * 3);
result.NormalData.reserve(numTriangles * 3);
result.TexCoordData.reserve(numTriangles * 3);
for (uint32_t i = 0; i < numTriangles; ++i)
{
for (int k = 0; k < 3; ++k)
{
uint32_t idx = *reinterpret_cast<const uint32_t*>(ptr); ptr += 4;
if (idx >= numVertices)
throw std::runtime_error("Triangle index out of range in: " + fileName);
result.PositionData.push_back(positions[idx]);
result.NormalData.push_back(normals[idx]);
result.TexCoordData.push_back(uvs[idx]);
}
}
std::cout << "Binary model loaded: " << numVertices << " verts, " << numTriangles << " tris." << std::endl;
s_meshCache[key] = result;
return result;
}
}
+1
View File
@@ -7,4 +7,5 @@
namespace ZL
{
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName = "");
VertexDataStruct LoadModelFromBinFile(const std::string& fileName, const std::string& ZIPFileName = "");
}
+8 -2
View File
@@ -138,7 +138,10 @@ namespace ZL {
// Load mesh
try {
gameObj.mesh.data = LoadFromTextFile02(objData.meshPath, zipPath);
if (objData.meshPath.size() > 4 && objData.meshPath.compare(objData.meshPath.size() - 4, 4, ".bin") == 0)
gameObj.mesh.data = LoadModelFromBinFile(objData.meshPath, zipPath);
else
gameObj.mesh.data = LoadFromTextFile02(objData.meshPath, zipPath);
}
catch (const std::exception& e) {
std::cerr << "GameObjectLoader: Failed to load mesh for '" << objData.name << "': " << e.what() << std::endl;
@@ -211,7 +214,10 @@ namespace ZL {
// Load mesh
try {
intObj.mesh.data = LoadFromTextFile02(objData.meshPath, zipPath);
if (objData.meshPath.size() > 4 && objData.meshPath.compare(objData.meshPath.size() - 4, 4, ".bin") == 0)
intObj.mesh.data = LoadModelFromBinFile(objData.meshPath, zipPath);
else
intObj.mesh.data = LoadFromTextFile02(objData.meshPath, zipPath);
}
catch (const std::exception& e) {
std::cerr << "GameObjectLoader: Failed to load mesh for interactive '" << objData.name << "': " << e.what() << std::endl;