From 74f9362cf30a0a24f6acd1a17440973c1a900521 Mon Sep 17 00:00:00 2001 From: Joel Kiptoo Date: Mon, 5 Oct 2026 12:16:12 +0300 Subject: [PATCH 1/2] WaveFrontReader: read per-vertex colors from "v x y z r g b" Some tools, such as MeshLab, write a per-vertex color after the position on 'v' lines. The reader ignored everything after x y z, so these colors were dropped. When a 'v' line has exactly three extra values they are read as an RGB color. A single extra value is still treated as the optional 'w' coordinate and ignored. Positions without a color default to white. The colors go into a new vertexColors array, one entry per vertex, alongside a hasVertexColors flag. Vertex itself is unchanged, so the .vbo format and existing callers are unaffected. --- Utilities/WaveFrontReader.h | 53 ++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/Utilities/WaveFrontReader.h b/Utilities/WaveFrontReader.h index 6633c041..bbb4f71c 100644 --- a/Utilities/WaveFrontReader.h +++ b/Utilities/WaveFrontReader.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,8 @@ namespace DX WaveFrontReader() noexcept : hasNormals(false), - hasTexcoords(false) + hasTexcoords(false), + hasVertexColors(false) {} HRESULT Load(_In_z_ const wchar_t* szFileName, bool ccw = true, bool loadmtl = true) @@ -107,6 +109,7 @@ namespace DX std::vector positions; std::vector normals; std::vector texCoords; + std::vector positionColors; VertexCache vertexCache; @@ -152,6 +155,32 @@ namespace DX float x, y, z; InFile >> x >> y >> z; positions.emplace_back(XMFLOAT3(x, y, z)); + + // Some tools (e.g. MeshLab) write a per-vertex color after the position as + // "v x y z r g b". This is not part of the OBJ specification, so only exactly + // three extra values are treated as a color; a single extra value is the + // optional 'w' coordinate and is ignored. + XMFLOAT3 color(1.f, 1.f, 1.f); + + std::wstring rest; + std::getline(InFile, rest, L'\n'); + InFile.putback(L'\n'); + + std::wistringstream extra(rest); + extra.imbue(std::locale::classic()); + + float values[4] = {}; + size_t count = 0; + while (count < std::size(values) && extra >> values[count]) + ++count; + + if (count == 3) + { + color = XMFLOAT3(values[0], values[1], values[2]); + hasVertexColors = true; + } + + positionColors.emplace_back(color); } else if (0 == wcscmp(strCommand.c_str(), L"vt")) { @@ -284,6 +313,12 @@ namespace DX if (index == uint32_t(-1)) return E_OUTOFMEMORY; + if (index == vertexColors.size()) + { + // New vertex: its color comes from the position it was built from + vertexColors.emplace_back(positionColors[vertexIndex]); + } + constexpr uint32_t maxIndex = (sizeof(index_t) == 2) ? UINT16_MAX : UINT32_MAX; if (index >= maxIndex) { @@ -399,6 +434,11 @@ namespace DX if (positions.empty()) return E_FAIL; + if (!hasVertexColors) + { + vertexColors.clear(); + } + // Cleanup InFile.close(); @@ -617,9 +657,11 @@ namespace DX indices.clear(); attributes.clear(); materials.clear(); + vertexColors.clear(); name.clear(); - hasNormals = false; - hasTexcoords = false; + hasNormals = false; + hasTexcoords = false; + hasVertexColors = false; bounds.Center.x = bounds.Center.y = bounds.Center.z = 0.f; bounds.Extents.x = bounds.Extents.y = bounds.Extents.z = 0.f; @@ -739,9 +781,14 @@ namespace DX std::vector attributes; std::vector materials; + // Per-vertex colors from the non-standard "v x y z r g b" extension, one per entry in + // 'vertices'. Only filled in when hasVertexColors is true. + std::vector vertexColors; + std::wstring name; bool hasNormals; bool hasTexcoords; + bool hasVertexColors; DirectX::BoundingBox bounds; From 7cb75cbf002f1dfa13cd34ef9d0a9b642d1d1622 Mon Sep 17 00:00:00 2001 From: Joel Kiptoo Date: Fri, 9 Oct 2026 09:11:03 +0300 Subject: [PATCH 2/2] WaveFrontReader: apply clang-format --- Utilities/WaveFrontReader.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Utilities/WaveFrontReader.h b/Utilities/WaveFrontReader.h index bbb4f71c..d7794abe 100644 --- a/Utilities/WaveFrontReader.h +++ b/Utilities/WaveFrontReader.h @@ -169,14 +169,14 @@ namespace DX std::wistringstream extra(rest); extra.imbue(std::locale::classic()); - float values[4] = {}; - size_t count = 0; + float values[4] = {}; + size_t count = 0; while (count < std::size(values) && extra >> values[count]) ++count; if (count == 3) { - color = XMFLOAT3(values[0], values[1], values[2]); + color = XMFLOAT3(values[0], values[1], values[2]); hasVertexColors = true; }