Delphi 7 obj reading

Started by
15 comments, last by SuBXaX 13 years, 9 months ago
Quote:Original post by Buckeye
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 don't think it's looping indefinitely, because i'v created a new project and created a text file with 9 v letters and 9 numbers like that:

v 1v 2v 3v 4v 5v 6v 7v 8v 9


And it doesn't get stuck, everythings okay, works perfect. When i'v tried reading obj format file, it get's stuck, i think that's because there are many simbols there.

EDIT: I don't think that there is switch statment in Delphi

[Edited by - SuBXaX on July 11, 2010 9:33:44 AM]
Advertisement
Quote:I don't think it's looping indefinitely ..it get's stuck

Still don't know what you mean by getting "stuck." "Stuck" is not a technical term. Can you describe what happens?

1. It may be that your OBJ has Return/Linefeed at the end of each line and Delphi wants only Return. You can create a text file of your own (since it appears you can do that) and type in some of the lines from the OBJ file to test that.

2. Put some other lines in your text file, such as a blank line and "# this is a comment" to challenge your parsing.

EDIT: I think the equivalent of switch is the Case statement in delphi.

Something like:
Read(F,firstLetter);Case firstLetter of   'v': // do vertex processing   'f': // do face processingElse // handle unknown lines

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've finaly figure it out, i wouldn't made it without your help Buckeye. Thank you very much! :))
Good for you. HOWEVER, others may run into the same problem. As a community benefit, post the solution to the problem.

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.

Delphi has a switching construct. Please see:
Delphi: Case statement

Edit: Damn, I'm somewhat slow today...
I've modified your code a bit. Your buffer, although working can be defined as just a string. Also, comments and empty lines can be easily ignored. Furthermore I've added a case block (as suggested by Buckeye) to improve readability.

I tried this code on a random obj file I found and it worked quite well. The number of faces is the same as what is reported by my 3d software.

procedure TForm1.Import(failas : string);var F : TextFile;   Buffer : string;begin  vertexCount := 0;  facesCount := 0;  texCoordsCount := 0;  normalsCount := 0;  AssignFile(F,failas);  Reset(F);  while not Eof(F) do  begin    Readln(F,Buffer);    if (Buffer <> '') and (Buffer[1] <> '#') then    case buffer[1] of      'v' : inc(vertexCount);      'f' : inc(facesCount);      'n' : inc(normalsCount);      't' : inc(texCoordsCount);    end;  end;  memo1.Clear;  memo1.Lines.add('FacesCount = ' + IntToStr(facesCount));  memo1.Lines.add('VertexCount = ' + IntToStr(vertexCount));  memo1.Lines.add('NormalsCount = ' + IntToStr(normalsCount));  CloseFile(F);end;


Edit: see here for a complete obj loader written in delphi.
The solution to fix the problem is that, there were some spaces in the file, you need to throw them away:

AssignFile(F,failas);  Reset(F);  while not Eof(F) do  begin  Read(F,buffer[0]);  if buffer[0] = 'v' then   begin      vertexCount := vertexCount + 1;      Readln(F,vertex[vertexCount].x,vertex[vertexCount].y,vertex[vertexCount].z);   end   else if buffer[0] = 'f' then   begin      facesCount := facesCount + 1;      Readln(F, vertices[facesCount].v1, texNormals[facesCount].tv1, normals[facesCount].nv1,                  vertices[facesCount].v2, texNormals[facesCount].tv2, normals[facesCount].nv2,                  vertices[facesCount].v3, texNormals[facesCount].tv3, normals[facesCount].nv3);   end   else if buffer[0] = 'n' then   begin      normalsCount := normalsCount + 1;      Readln(F, normals2[normalsCount].x,normals2[normalsCount].y,normals2[normalsCount].z);   end   else if buffer[0] = 't' then   begin    texCoordsCount := texCoordsCount + 1;    Readln(F, texCoords[texCoordsCount].x,texCoords[texCoordsCount].y,texCoords[texCoordsCount].z);   end   else Readln(F,buffer[0]); // Throwing away the spaces!  end;


Program will work perfectly.

This topic is closed to new replies.

Advertisement