@@ -18,16 +18,16 @@ namespace {
1818
1919bool PlyParser::parse (const std::string& path, MeshData& out) {
2020 std::vector<unsigned char > file;
21- if (!loadBinaryFile (file, path))
22- return false ;
21+ if (!loadBinaryFile (file, path)) return false ;
2322
24- if (file.empty ()) return Logger::error (" PlyParser" , " parse" , " Input pointer is null\n " );
23+ if (file.empty () || file[0 ] == ' \0 ' )
24+ return Logger::error (" PlyParser" , " parse" , " File is empty" );
2525
2626 const unsigned char * p = file.data ();
2727 std::string errorMsg;
2828 while (true ) {
2929 if (!parseHeaderLine (p, out.numVertices , out.numTriangles , out.hasNormals , out.hasColours , out.hasTexCoords )) {
30- errorMsg = " header or missing 'end_header'" ;
30+ errorMsg = " header, 'end_header' not found " ;
3131 break ;
3232 }
3333
@@ -55,16 +55,17 @@ bool PlyParser::parse(const std::string& path, MeshData& out) {
5555 out.indices .clear ();
5656 out.vertices .clear ();
5757 out.numVertices = out.numIndices = out.numTriangles = 0 ;
58- return Logger::error (" PlyParser" , " parse" , (" Failed to parse " + errorMsg + ' \n ' ).c_str ());
58+ return Logger::error (" PlyParser" , " parse" , (" Failed to parse " + errorMsg).c_str ());
5959}
6060
6161bool PlyParser::parseHeaderLine (const unsigned char *& p, unsigned int & numVerticesOut, unsigned int & numTrianglesOut, bool & hasNormalsOut, bool & hasColoursOut, bool & hasTexCoordsOut) {
62- if (!p) return Logger::error (" PlyParser" , " parseHeaderLine" , " Input pointer is null\n " );
62+ if (!p) return Logger::error (" PlyParser" , " parseHeaderLine" , " Input pointer is null" );
6363 p = skipWhitespace (p);
6464
6565 bool hasNx = false , hasNy = false , hasNz = false ;
6666 bool hasRed = false , hasGreen = false , hasBlue = false ;
6767 bool hasU = false , hasV = false ;
68+
6869 while (*p) {
6970 const unsigned char * nextLine = skipToNextLine (p);
7071 const unsigned char * lineEnd = trimEOL (p, nextLine);
@@ -97,11 +98,11 @@ bool PlyParser::parseHeaderLine(const unsigned char*& p, unsigned int& numVertic
9798 p = nextLine;
9899 }
99100
100- return Logger::error ( " plyParser " , " parseHeaderLine " , " Failed, end of buffer reached " ) ;
101+ return false ;
101102}
102103
103104bool PlyParser::parseElementLine (const unsigned char *& p, unsigned int & verticesOut, unsigned int & trianglesOut) {
104- if (!p) return Logger::error (" PlyParser" , " parseElementLine" , " Input pointer is null\n " );
105+ if (!p) return Logger::error (" PlyParser" , " parseElementLine" , " Input pointer is null" );
105106
106107 p = skipWhitespace (p += 7 );
107108 if (strncmp ((const char *)p, " vertex" , 6 ) == 0 && (p[6 ] == ' ' || p[6 ] == ' \t ' )) {
@@ -115,47 +116,44 @@ bool PlyParser::parseElementLine(const unsigned char*& p, unsigned int& vertices
115116 return false ;
116117}
117118bool PlyParser::parsePropertyLine (const unsigned char *& p, bool & hasNx, bool & hasNy, bool & hasNz, bool & hasR, bool & hasG, bool & hasB, bool & hasU, bool & hasV) {
118- if (!p) return Logger::error (" PlyParser" , " parsePropertyLine" , " Input pointer is null\n " );
119+ if (!p) return Logger::error (" PlyParser" , " parsePropertyLine" , " Input pointer is null" );
119120 p = skipWhitespace (p += 8 );
120121
121122 char type[32 ]{};
122123 if (!parseToken (p, (unsigned char *)type, sizeof (type)))
123- return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property type : " + std::string (type));
124+ return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property type: " + std::string (type));
124125
125126 if (strcmp (type, " list" ) == 0 ) {
126- /*
127- 1 = Count Type
128- 2 = Value Type
129- 3 = Property Name
130- */
131- char property[3 ][32 ]{};
132- for (int i = 0 ; i < 3 ; ++i)
133- if (!parseToken (p, reinterpret_cast <unsigned char *>(property[i]), sizeof (property[i])))
134- return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property list type, number: " + std::to_string (i));
135-
127+ char countType[32 ]{}, valueType[32 ]{}, propertyName[32 ]{};
128+ if (!parseToken (p, reinterpret_cast <unsigned char *>(countType), sizeof (countType)))
129+ return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property list: count type" );
130+ if (!parseToken (p, reinterpret_cast <unsigned char *>(valueType), sizeof (valueType)))
131+ return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property list: value type" );
132+ if (!parseToken (p, reinterpret_cast <unsigned char *>(propertyName), sizeof (propertyName)))
133+ return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property list: property name" );
136134 return true ;
137135 }
138136
139137 char propertyName[32 ]{};
140138 if (!parseToken (p, (unsigned char *)propertyName, sizeof (propertyName)))
141- return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property name : " + std::string (propertyName));
139+ return Logger::error (" PlyParser" , " parsePropertyLine" , " Failed to parse property name: " + std::string (propertyName));
142140
143- if (strcmp (propertyName, " nx" ) == 0 || strcmp (propertyName, " normal_x" ) == 0 ) hasNx = true ;
141+ if (strcmp (propertyName, " nx" ) == 0 || strcmp (propertyName, " normal_x" ) == 0 ) hasNx = true ;
144142 else if (strcmp (propertyName, " ny" ) == 0 || strcmp (propertyName, " normal_y" ) == 0 ) hasNy = true ;
145143 else if (strcmp (propertyName, " nz" ) == 0 || strcmp (propertyName, " normal_z" ) == 0 ) hasNz = true ;
146- else if (strcmp (propertyName, " red" ) == 0 ) hasR = true ;
144+ else if (strcmp (propertyName, " red" ) == 0 ) hasR = true ;
147145 else if (strcmp (propertyName, " green" ) == 0 ) hasG = true ;
148- else if (strcmp (propertyName, " blue" ) == 0 ) hasB = true ;
146+ else if (strcmp (propertyName, " blue" ) == 0 ) hasB = true ;
149147 else if (strcmp (propertyName, " u" ) == 0 || strcmp (propertyName, " texture_u" ) == 0 ) hasU = true ;
150148 else if (strcmp (propertyName, " v" ) == 0 || strcmp (propertyName, " texture_v" ) == 0 ) hasV = true ;
151149 return true ;
152150}
153151
154152bool PlyParser::parseVertices (const unsigned char *& p, MeshData& out) {
155- if (!p) return Logger::error (" PlyParser" , " parseVertices" , " Input pointer is null\n " );
156- if (!out.numVertices ) return Logger::error (" PlyParser" , " parseVertices" , " No vertices declared in header\n " );
153+ if (!p) return Logger::error (" PlyParser" , " parseVertices" , " Input pointer is null" );
154+ if (!out.numVertices ) return Logger::error (" PlyParser" , " parseVertices" , " No vertices declared in header" );
157155
158- float minY = FLT_MAX , maxY = -FLT_MAX ;
156+ float minY = FLT_MAX , maxY = -FLT_MAX ;
159157 unsigned int i = 0 ;
160158 while (i < out.numVertices && *p) {
161159 Math::Vertex& v = out.vertices [i];
@@ -167,83 +165,54 @@ bool PlyParser::parseVertices(const unsigned char*& p, MeshData& out) {
167165 continue ;
168166 }
169167
170- if (*p == ' \0 ' ) return false ;
168+ if (*p == ' \0 ' ) return Logger::error ( " PlyParser " , " parseVertices " , " Unexpected end of data " ) ;
171169
172- bool valid = true ;
173- while (valid) {
174- STARLET_PARSE_OR (valid = false , parseFloat, v.pos .x , " Failed to parse position X" );
175- STARLET_PARSE_OR (valid = false , parseFloat, v.pos .y , " Failed to parse position Y" );
176- STARLET_PARSE_OR (valid = false , parseFloat, v.pos .z , " Failed to parse position Z" );
177- break ;
178- }
179- if (!valid) {
180- p = nextLine;
181- continue ;
182- }
170+ if (!parseFloat (p, v.pos .x ))
171+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse position X at vertex " + std::to_string (i));
172+ if (!parseFloat (p, v.pos .y ))
173+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse position Y at vertex " + std::to_string (i));
174+ if (!parseFloat (p, v.pos .z ))
175+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse position Z at vertex " + std::to_string (i));
183176
184177 if (out.hasNormals ) {
185- while (valid) {
186- STARLET_PARSE_OR (valid = false , parseFloat, v.norm .x , " Failed to parse normal X" );
187- STARLET_PARSE_OR (valid = false , parseFloat, v.norm .y , " Failed to parse normal Y" );
188- STARLET_PARSE_OR (valid = false , parseFloat, v.norm .z , " Failed to parse normal Z" );
189- break ;
190- }
191-
192- if (!valid) {
193- p = nextLine;
194- continue ;
195- }
178+ if (!parseFloat (p, v.norm .x ))
179+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse normal X at vertex " + std::to_string (i));
180+ if (!parseFloat (p, v.norm .y ))
181+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse normal Y at vertex " + std::to_string (i));
182+ if (!parseFloat (p, v.norm .z ))
183+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse normal Z at vertex " + std::to_string (i));
196184 }
197185
198186 if (out.hasColours ) {
199- if (*p != ' \0 ' ) {
200- Math::Vec3 colour = { 1 .0f , 1 .0f , 1 .0f };
201- const unsigned char * original = p;
202- while (valid) {
203- STARLET_PARSE_OR (valid = false , parseFloat, colour.r , " Failed to parse float colour R" );
204- STARLET_PARSE_OR (valid = false , parseFloat, colour.g , " Failed to parse float colour G" );
205- STARLET_PARSE_OR (valid = false , parseFloat, colour.b , " Failed to parse float colour B" );
206- break ;
207- }
208-
209- if (valid &&
210- colour.x >= 0 .0f && colour.x <= 1 .0f &&
211- colour.y >= 0 .0f && colour.y <= 1 .0f &&
212- colour.z >= 0 .0f && colour.z <= 1 .0f ) {
213- v.col = Math::Vec4{ colour.x , colour.y , colour.z , 1 .0f };
214- out.hasColours = true ;
215- }
216- else {
217- p = original;
218- unsigned int ri = 0 , gi = 0 , bi = 0 , ai = 256 ;
219-
220- valid = true ;
221- while (valid) {
222- STARLET_PARSE_OR (valid = false , parseUInt, ri, " " );
223- STARLET_PARSE_OR (valid = false , parseUInt, gi, " " );
224- STARLET_PARSE_OR (valid = false , parseUInt, bi, " " );
225- break ;
226- }
227- if (!parseUInt (p, ai)) ai = 255 ;
228-
229- if (valid && ri <= 255 && gi <= 255 && bi <= 255 ) {
230- v.col = Math::Vec4{
231- static_cast <float >(ri) / 255 .0f ,
232- static_cast <float >(gi) / 255 .0f ,
233- static_cast <float >(bi) / 255 .0f ,
234- static_cast <float >(ai) / 255 .0f
235- };
236- }
237- }
187+ const unsigned char * original = p;
188+ Math::Vec3 colour = { 1 .0f , 1 .0f , 1 .0f };
189+
190+ if (parseFloat (p, colour.r ) &&
191+ parseFloat (p, colour.g ) &&
192+ parseFloat (p, colour.b ) &&
193+ colour.r <= 1 .0f && colour.g <= 1 .0f && colour.b <= 1 .0f ) {
194+ v.col = Math::Vec4{ colour.r , colour.g , colour.b , 1 .0f };
195+ } else {
196+ p = original;
197+ unsigned int ri = 0 , gi = 0 , bi = 0 , ai = 256 ;
198+
199+ if (!parseUInt (p, ri) || !parseUInt (p, gi) || !parseUInt (p, bi))
200+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse colour at vertex " + std::to_string (i));
201+ if (ri > 255 || gi > 255 || bi > 255 )
202+ return Logger::error (" PlyParser" , " parseVertices" , " Colour out of range at vertex " + std::to_string (i));
203+
204+ parseUInt (p, ai);
205+ if (ai > 255 ) ai = 255 ;
206+
207+ v.col = Math::Vec4{ ri / 255 .0f , gi / 255 .0f , bi / 255 .0f , ai / 255 .0f };
238208 }
239209 }
240210
241211 if (out.hasTexCoords ) {
242- while (valid) {
243- STARLET_PARSE_OR (valid = false , parseFloat, v.texCoord .x , " Failed to parse texcoord U" );
244- STARLET_PARSE_OR (valid = false , parseFloat, v.texCoord .y , " Failed to parse texcoord V" );
245- break ;
246- }
212+ if (!parseFloat (p, v.texCoord .x ))
213+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse texCoord X at vertex " + std::to_string (i));
214+ if (!parseFloat (p, v.texCoord .y ))
215+ return Logger::error (" PlyParser" , " parseVertices" , " Failed to parse texCoord Y at vertex " + std::to_string (i));
247216 }
248217
249218 if (v.pos .y < minY) minY = v.pos .y ;
@@ -262,10 +231,13 @@ bool PlyParser::parseVertices(const unsigned char*& p, MeshData& out) {
262231}
263232bool PlyParser::parseIndices (const unsigned char *& p, MeshData& out) {
264233 if (!p) return Logger::error (" PlyParser" , " parseIndices" , " Input pointer is null" );
265- if (out.indices .empty () || out.numIndices == 0 ) return Logger::error (" PlyParser" , " parseIndices" , " Index buffer not allocated" );
234+ if (out.indices .empty () || out.numIndices == 0 )
235+ return Logger::error (" PlyParser" , " parseIndices" , " Index buffer not allocated" );
236+
237+ unsigned int i = 0 ;
238+ while (i < out.numTriangles ) {
239+ if (!p || *p == ' \0 ' ) break ;
266240
267- unsigned int triangleIndex = 0 ;
268- while (triangleIndex < out.numTriangles && *p) {
269241 const unsigned char * nextLine = skipToNextLine (p);
270242 const unsigned char * lineEnd = trimEOL (p, nextLine);
271243
@@ -276,40 +248,31 @@ bool PlyParser::parseIndices(const unsigned char*& p, MeshData& out) {
276248
277249 unsigned int count = 0 ;
278250 if (!parseUInt (p, count)) {
279- p = nextLine ;
280- continue ;
251+ if (* p == ' \0 ' ) break ;
252+ return Logger::error ( " PlyParser " , " parseIndices " , " Failed to parse face vertex count at triangle " + std::to_string (i)) ;
281253 }
282254
283- if (count != 3 ) {
284- p = nextLine;
285- continue ;
286- }
255+ if (count != 3 )
256+ return Logger::error (" PlyParser" , " parseIndices" , " Non-triangle face detected (vertex count: " + std::to_string (count) + " ) at triangle " + std::to_string (i));
287257
288258 unsigned int i0{ 0 }, i1{ 0 }, i2{ 0 };
289- bool valid = true ;
290- while (valid) {
291- STARLET_PARSE_OR (valid = false , parseUInt, i0, " Failed to parse index 1" );
292- STARLET_PARSE_OR (valid = false , parseUInt, i1, " Failed to parse index 2" );
293- STARLET_PARSE_OR (valid = false , parseUInt, i2, " Failed to parse index 3" );
294- break ;
295- }
259+ if (!parseUInt (p, i0) || !parseUInt (p, i1) || !parseUInt (p, i2))
260+ return Logger::error (" PlyParser" , " parseIndices" , " Failed to parse face indices at triangle " + std::to_string (i));
296261
297- if (valid) {
298- if (i0 >= out.numVertices || i1 >= out.numVertices || i2 >= out.numVertices )
299- return Logger::error (" PlyParser" , " parseIndices" , " Index out of bounds: face references vertex >= " + std::to_string (out.numVertices ));
300-
301- unsigned int base = triangleIndex * 3 ;
302- out.indices [static_cast <size_t >(base) + 0 ] = i0;
303- out.indices [static_cast <size_t >(base) + 1 ] = i1;
304- out.indices [static_cast <size_t >(base) + 2 ] = i2;
305- ++triangleIndex;
306- }
262+ if (i0 >= out.numVertices || i1 >= out.numVertices || i2 >= out.numVertices )
263+ return Logger::error (" PlyParser" , " parseIndices" , " Index out of bounds at triangle " + std::to_string (i));
264+
265+ size_t base = static_cast <size_t >(i) * 3 ;
266+ out.indices [base + 0 ] = i0;
267+ out.indices [base + 1 ] = i1;
268+ out.indices [base + 2 ] = i2;
269+ ++i;
307270
308271 p = nextLine;
309272 }
310273
311- if (triangleIndex != out.numTriangles )
312- return Logger::error (" PlyParser" , " parseIndices" , " Face count declared: " + std::to_string (out.numTriangles ) + " but parsed: " + std::to_string (triangleIndex ));
274+ if (i != out.numTriangles )
275+ return Logger::error (" PlyParser" , " parseIndices" , " Face count declared: " + std::to_string (out.numTriangles ) + " but parsed: " + std::to_string (i ));
313276
314277 return true ;
315278}
0 commit comments