Delphi 7 obj reading

Started by
15 comments, last by SuBXaX 13 years, 9 months ago
Hello everybody, i'm reading an obj file with delphi 7. Problem is that when i'm just calculating vertices, faces and normals, the count of them is great. But if i try to read, the count of faces, vertices and normals divides by 3 or 2 times. That is very strange issue, wich i can't figure out.

The code:

Here i'm just calculating vertices, faces and normals
procedure TForm1.Import(failas : string);var F : TextFile;begin  AssignFile(F,failas);  Reset(F);  vertexCount := 0;  facesCount := 0;  texCoordsCount := 0;  normalsCount := 0;  while not Eof(F) do  begin    Readln(F,buffer[0]);  if buffer[0] = 'v' then   begin    vertexCount := vertexCount + 1;    //Read(F,buffer[0],vertex[vertexCount].x,vertex[vertexCount].y,vertex[vertexCount].z);   end   else if buffer[0] = 'f' then   begin    facesCount := facesCount + 1;    //Read(F, buffer[0], vertices[facesCount].v1, texNormals[facesCount].v1, normals[facesCount].v1,                         //vertices[facesCount].v2, texNormals[facesCount].v2, normals[facesCount].v2,                         //vertices[facesCount].v3, texNormals[facesCount].v3, normals[facesCount].v3);   end   else if buffer[0] = 'n' then   begin    normalsCount := normalsCount + 1;    //Read(F, buffer[0], normals2[normalsCount].x, normals2[normalsCount].y, normals2[normalsCount].z);   end   else if buffer[0] = 't' then   begin   texCoordsCount := texCoordsCount + 1;    //Read(F, buffer[0], texCoords[texCoordsCount].x,texCoords[texCoordsCount].y,texCoords[texCoordsCount].z);   end  end;  memo1.Lines.add('FacesCount = ' + IntToStr(facesCount));  memo1.Lines.add('VertexCount = ' + IntToStr(vertexCount));  memo1.Lines.add('NormalsCount = ' + IntToStr(normalsCount));  CloseFile(F);end;


Result:
FacesCount = 2256VertexCount = 1178NormalsCount = 1178


If i try to read, result is:
FacesCount = 1128VertexCount = 589NormalsCount = 589


Any ideas?
Advertisement
First, I'm not familiar with Delphi. However, it appears that the sequence:

Readln(...);
Read(...);

would read 2 lines from the file. If that's correct, then you Readln a line, then Read another line without increasing the count.

According to the documentation, Readln() moves the read position of the file to the beginning of the next line. So a subsequent Read() is not from the same line you've just counted.

Example:

If the file is something like:

v x0 y0 z0
v x1 y1 z1

Then:
Readln(); // get x0,y0,z0 - count is 1
Readln(); // get x1,y1,z1 - count is 2

However:
Readln(); // get x0,y0,z0 - count is 1
Read(); // get x1,y1,z1 - count is still 1!

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


How is buffer declared? Is it big enough to hold the data you read in?
--- "A penny saved never boils."
Quote:Original post by Whatz

How is buffer declared? Is it big enough to hold the data you read in?


Buffer = array [0..5000] of string[1]


[Edited by - SuBXaX on July 11, 2010 7:30:35 AM]
Quote:Original post by Buckeye
First, I'm not familiar with Delphi. However, it appears that the sequence:

Readln(...);
Read(...);

would read 2 lines from the file. If that's correct, then you Readln a line, then Read another line without increasing the count.

According to the documentation, Readln() moves the read position of the file to the beginning of the next line. So a subsequent Read() is not from the same line you've just counted.

Example:

If the file is something like:

v x0 y0 z0
v x1 y1 z1

Then:
Readln(); // get x0,y0,z0 - count is 1
Readln(); // get x1,y1,z1 - count is 2

However:
Readln(); // get x0,y0,z0 - count is 1
Read(); // get x1,y1,z1 - count is still 1!


I'v tried using Readln and Read function the result is the same :(

Quote:I'v tried using Readln and Read function the result is the same :(

You missed my point. If you uncomment the //Read() lines, you only increment the count once for each two lines you read.

Readln(); // read in vertex 1. After Readln(), file pointer is at beginning of line 2
count = count+1 // count = 1
Read(); // read in vertex 2. After Read(), file pointer is at end of line 2 or beginning of line 3

Readln(); // read in vertex 3
count = count+1 // count = 2
Read(); // read in vertex 4

4 vertices read. count = 2

After you do a Readln() and determine whether it's a vertex, normal, etc., you have to get the vertex/face/etc. data from the buf you just read in. Don't do another Read or Readln!

Something like:
Readln(buf);if( buf[0]=='v'){   increase v count;   // get the vertex data from buf. Don't do another Read or Readln} else if( buf[0]=='f' ){   increase f count;   // get the face data from buf. Don't do another Read or Readln} .. //etc.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I get the point. Program is reading data from every 2 lines, but how i can fix this?
Simultaneous posts. I edited my previous post.

After you do a Readln() and determine if it's a v, f, etc., process the vertex/face/etc. data you just read into your buffer.

Perhaps you can do something like:
Read(F,character C) // read in first character of lineif( C = 'v' ){   vcount = vcount+1;   Readln(.. vertex values); // read in rest of line} else if ( C='f' ){   fcount = fcount+1;   Readln(.. face values);} .. etc.

I'm not a Delphi person, but something like that should work.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

It's working, but it's very slow, program get's stuck. Ohh i wish there would be a way to make it faster, because i'v writen obj loader on C++ and it's very fast. On delphi program get's stuck.
If Delphi is like the old Turbo Pascal I used to use, there is a lot of run-time type checking to keep things "safe" for you. That may be the problem. But it shouldn't be really slow.

When you say it gets "stuck," do you mean it loops indefinitely and you have to kill the program? If so, you may have to check for EOF after each Read and Readln.

This article does something like you're doing. You may want to take a look at it.

EDIT: You have to handle lines that don't begin with a recognized character. OBJ files allow comment lines, blank lines, etc.

For instance, if you have a comment line in your OBJ file:
Read(F,letter); // read in "/"if( letter='..') // readlnelse if( letter='..' // readln

then you won't read and throw away the comment line. The next time you Read(F,letter) it will be just the next character in the comment line.

That may why it's so slow. If you have a line that doesn't begin with v, f, n or t you read the entire line character by character.

Your "if, else if" sequence must account for all possibilities.

I can't remember if Delphi has the equivalent of a switch statement, but a better approach would be:
Read(F,letter);switch( letter ){   case 'v': // handle vertices   case 'f': // handle faces   ...   default: Readln(F,text); // throw away an unrecognized line??}


[Edited by - Buckeye on July 11, 2010 9:05:23 AM]

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement