手动UV分支
This commit is contained in:
1 parent
5e1623e303
commit
7fd81ffbea
7 files changed
+1192
-242
No files matched your search
+128
-1
@@ -48,6 +48,7 @@ ObjModel::MaterialLib::MaterialLib()
|
||||
|
||||
bool ObjModel::MaterialLib::Save(const String& prefix, bool texLossless) const
|
||||
{
|
||||
DEBUG_EXTRA("MaterialLib::Save %s", prefix.c_str());
|
||||
std::ofstream out((prefix+".mtl").c_str());
|
||||
if (!out.good())
|
||||
return false;
|
||||
@@ -130,7 +131,7 @@ bool ObjModel::MaterialLib::Load(const String& fileName)
|
||||
|
||||
// S T R U C T S ///////////////////////////////////////////////////
|
||||
|
||||
bool ObjModel::Save(const String& fileName, unsigned precision, bool texLossless) const
|
||||
bool ObjModel::Save(const String& fileName, unsigned precision, bool texLossless, bool bUseExistingUV) const
|
||||
{
|
||||
if (vertices.empty())
|
||||
return false;
|
||||
@@ -140,6 +141,9 @@ bool ObjModel::Save(const String& fileName, unsigned precision, bool texLossless
|
||||
if (!material_lib.Save(prefix, texLossless))
|
||||
return false;
|
||||
|
||||
if (bUseExistingUV)
|
||||
return true;
|
||||
|
||||
std::ofstream out((prefix + ".obj").c_str());
|
||||
if (!out.good())
|
||||
return false;
|
||||
@@ -269,6 +273,129 @@ bool ObjModel::Load(const String& fileName)
|
||||
return !vertices.empty();
|
||||
}
|
||||
|
||||
bool ObjModel::LoadUV(const String& fileName, SEACAVE::cList<TexCoord,const TexCoord&,0,8192,uint32_t> &faceTexcoords, bool bLoadUV)
|
||||
{
|
||||
DEBUG_EXTRA("LoadUV bLoadUV=%b", bLoadUV);
|
||||
ASSERT(vertices.empty() && groups.empty() && material_lib.materials.empty());
|
||||
std::ifstream fin(fileName.c_str());
|
||||
String line, keyword;
|
||||
std::istringstream in;
|
||||
|
||||
while (fin.good()) {
|
||||
std::getline(fin, line);
|
||||
if (line.empty() || line[0u] == '#')
|
||||
continue;
|
||||
|
||||
in.str(line);
|
||||
in >> keyword;
|
||||
|
||||
if (keyword == "v") {
|
||||
Vertex v;
|
||||
in >> v[0] >> v[1] >> v[2];
|
||||
if (in.fail())
|
||||
{
|
||||
DEBUG_EXTRA("1");
|
||||
return false;
|
||||
}
|
||||
vertices.push_back(v);
|
||||
// DEBUG_EXTRA("10, %d", vertices.size());
|
||||
} else if (keyword == "vt") {
|
||||
TexCoord vt;
|
||||
in >> vt[0] >> vt[1];
|
||||
if (in.fail())
|
||||
{
|
||||
DEBUG_EXTRA("2");
|
||||
return false;
|
||||
}
|
||||
texcoords.push_back(vt);
|
||||
} else if (keyword == "vn") {
|
||||
Normal vn;
|
||||
in >> vn[0] >> vn[1] >> vn[2];
|
||||
if (in.fail())
|
||||
{
|
||||
DEBUG_EXTRA("3");
|
||||
return false;
|
||||
}
|
||||
normals.push_back(vn);
|
||||
} else if (keyword == "f") {
|
||||
Face f;
|
||||
memset(&f, 0xFF, sizeof(Face));
|
||||
|
||||
for (size_t k = 0; k < 3; ++k) {
|
||||
in >> keyword;
|
||||
|
||||
// 更健壮的解析方法,处理各种索引格式
|
||||
std::vector<String> parts;
|
||||
size_t start = 0, end = 0;
|
||||
|
||||
// 按'/'分割字符串
|
||||
while ((end = keyword.find('/', start)) != String::npos) {
|
||||
parts.push_back(keyword.substr(start, end - start));
|
||||
start = end + 1;
|
||||
}
|
||||
parts.push_back(keyword.substr(start));
|
||||
|
||||
// 根据分割后的部分数量处理不同情况
|
||||
if (parts.size() >= 1 && !parts[0].empty()) {
|
||||
f.vertices[k] = std::stoi(parts[0]) - OBJ_INDEX_OFFSET;
|
||||
}
|
||||
|
||||
if (parts.size() >= 2 && !parts[1].empty()) {
|
||||
f.texcoords[k] = std::stoi(parts[1]) - OBJ_INDEX_OFFSET;
|
||||
}
|
||||
|
||||
if (parts.size() >= 3 && !parts[2].empty()) {
|
||||
f.normals[k] = std::stoi(parts[2]) - OBJ_INDEX_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
if (in.fail())
|
||||
{
|
||||
DEBUG_EXTRA("4");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bLoadUV)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (f.texcoords[i] != NO_ID && f.texcoords[i] < texcoords.size()) {
|
||||
faceTexcoords.push_back(texcoords[f.texcoords[i]]);
|
||||
} else {
|
||||
// 索引无效(例如面定义中未提供vt索引或索引越界),使用默认值
|
||||
faceTexcoords.push_back(Point2f(0.0f, 0.0f)); // 默认UV
|
||||
DEBUG_EXTRA("Invalid texcoords %d", f.texcoords[i])
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG_EXTRA("faceTexcoords push_back [(%f,%f),(%f,%f),(%f,%f)]", texcoords[f.texcoords[0]].x, texcoords[f.texcoords[0]].y,
|
||||
// texcoords[f.texcoords[1]].x, texcoords[f.texcoords[1]].y, texcoords[f.texcoords[2]].x, texcoords[f.texcoords[2]].y);
|
||||
}
|
||||
|
||||
if (groups.empty())
|
||||
AddGroup("");
|
||||
groups.back().faces.push_back(f);
|
||||
// } else if (keyword == "mtllib") {
|
||||
// in >> keyword;
|
||||
// if (!material_lib.Load(keyword))
|
||||
// DEBUG_EXTRA("3");
|
||||
// return false;
|
||||
} else if (keyword == "usemtl") {
|
||||
Group group;
|
||||
in >> group.material_name;
|
||||
if (in.fail())
|
||||
{
|
||||
DEBUG_EXTRA("5");
|
||||
return false;
|
||||
}
|
||||
groups.push_back(group);
|
||||
}
|
||||
|
||||
in.clear();
|
||||
}
|
||||
|
||||
DEBUG_EXTRA("6, vertices.size=%d, faceTexcoords.size=%d", vertices.size(), faceTexcoords.size());
|
||||
return !vertices.empty();
|
||||
}
|
||||
|
||||
ObjModel::Group& ObjModel::AddGroup(const String& material_name)
|
||||
{
|
||||
|
||||
+2
-1
@@ -93,9 +93,10 @@ public:
|
||||
ObjModel() {}
|
||||
|
||||
// Saves the obj model to an .obj file, its material lib and the materials with the given file name
|
||||
bool Save(const String& fileName, unsigned precision=6, bool texLossless=false) const;
|
||||
bool Save(const String& fileName, unsigned precision=6, bool texLossless=false, bool bUseExistingUV=false) const;
|
||||
// Loads the obj model from an .obj file, its material lib and the materials with the given file name
|
||||
bool Load(const String& fileName);
|
||||
bool LoadUV(const String& fileName, SEACAVE::cList<TexCoord,const TexCoord&,0,8192,uint32_t> &faceTexcoords, bool bLoadUV = false);
|
||||
|
||||
// Creates a new group with the given material name
|
||||
Group& AddGroup(const String& material_name);
|
||||
|
||||
Reference in new issue
Block a user