Qbasicnews.com

Full Version: Binary file access trouble...
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Until now, I've never had a reason to open a file in binary mode that was created by another application, besides a bitmap loader I made.

I'm trying to extract the data in a Lightwave(.lwo) file. I've got the documentation and a start, but I've pretty much hit a brick wall.

Lightwave saves it's object files in binary chunks. Each chunk starts with an identity tag and the length of the data that follows.

Code:
CHUNK ::= tag[ID4], length[U4], data[...], pad[U1]

ID Tag
ID4
An ID tag is a sequence of 4 bytes interpreted as 7-bit ASCII values, usually upper-case. These tags are used to identify the type of data which follows. FORM, SURF, POLS, and LWOB are all examples of ID tags.

Signed Integer
I1, I2, I4

Unsigned Integer
I1, I2, I4
Integers can have 1, 2 or 4 bytes and can be signed or unsigned. The most significant byte comes first in the file, so bytes read into memory should be reversed before being interpreted on Intel and compatible CPUs.

Float
F4
Floats are written as 4 byte IEEE floating-point values. The bytes should generally be reversed before being interpreted on Intel and compatible CPUs.

String
S0
Names or other character strings are written as a series of ASCII character values followed by a zero (or null) byte. If the length of the string plus the null terminating byte is odd, an extra null is added to make the total length even.

Basically, I've created a type definition to mimic CHUNK.



Code:
'CHUNK ::= tag[ID4], length[U4], data[...], pad[U1]

Type DataChunkType
   Tag as String*4
   tLen as UINTEGER  
End Type

Dim Chunk as DataChunkType

This was just for testing purposes. I am only trying to get the polygon count at this point.

POLY is the ID tag for polygons, so I scan the file, byte by byte, until it encounters "POLY"....

Code:
DO
   i = i + 1
   Get #1, i, Chunk.Tag

   If Chunk.Tag = "POLY" THEN
      Get #1, i, Chunk
       Print Chunk.Tag
       Print Chunk. tLen
   End If
LOOP


Chunk.Tag still returns POLY, but Chunk.tLen returns some wild value, even if the obect only has one polygon.

Can somebody tell me what I'm doing wrong?


Thanx. Wink
Maybe it has something to do with the null byte that fb adds to its strings? I think your code reads "Poly" + one byte from the next 4bytes that give the poly count?
Yes, the static string *4 will be 5 bytes long - better to use a uinteger or 4-byte array.
How is it possible to have a 1 byte Integer? I must be missing something because that makes absolutely no sense to me. :???:


Also, what exactly do I need to do to reverse an unsiged integer? I'm thinking that I should load the value from the file into a string var, reverse the string and then stick it into an UINTEGER var using VAL(). Is this even close? I can't tell because everything except the ID tag srings is coming out of the file with insane values

For instance, I'm getting a return value of 1610612736 for the number of points in the object, but the object only has 8 points... it's just a simple cube, for god's sake!

Anonymous

a one byte integer is just a ubyte, i think

and, what theyre trying to say is, dont read the tag as a string * 4. read it as a uint and bitmask or shr the chars out one at a time, their ascii values will be the 4 values that comprise it. for instance



String: C T X W
Ascii: 83 84 88 87
Binary: 1010011 1010100 1011000 1010111

so your Tag, if read as a uint, will read as 175451223.

this could be the caus of youre erratic input, your uint perhaps was starting reading one byte late, because of the string termination.

you can do shr operations and bitmasks to extract the individual ascii values, and chr$ to construct them.
This is part of what is confusing me. Why do they have the Tag_Id's written in this binary file as regular strings?

The reason I need this so bad is because it would save alot of loading time in my games. Not to mention that this format saves the specular values, transparency, vertex colors, etc... That, and I wont have to create the models in modeler, take them into layout, animate them, save each animation frame as a seperate object, send them back to modeler and save each one as a seperate Wavefront(.OBJ) file. It's a ton of work.


Quote:FORM LWO2TAGS Face_1 Face_2 Face_3 LAYR  PNTS `¿À ¿À ¿À ?À ¿À ¿À ?À ¿À ?À ¿À ¿À ?À ¿À ?À ¿À ?À ?À ¿À ?À ?À ?À ¿À ?À ?À BBOX ¿À ¿À ¿À ?À ?À ?À POLS dFACE                                             PTAG 4SURF                
VMAD ¾TXUV Texture  ?€  ?€  ?€  ?€ ?€   ?€  ?€    ?€  ?€   ?€  ?€ ?€     ?€  ?€  ?€   ?€  ?€ ?€    ?€   ?€  ?€  ?€ ?€   ?€   ?€   ?€  ?€  ?€ ?€  ?€ 
?€ 

?€  ?€  ?€  ?€ ?€


Also, I have a C++ object loader that came with LW-SDK, but it has these #Define things, and I have no idea of how they work.

Code:
#define MAKE_ID(a,b,c,d)    \
    ((unsigned long) (a)<<24 | (unsigned long) (b)<<16 | \
     (unsigned long) (c)<<8 | (unsigned long) (d))

/* Universal IFF identifiers */

#define ID_FORM        MAKE_ID('F','O','R','M')
#define ID_LWO2        MAKE_ID('L','W','O','2')

/**  PRIMARY CHUNK ID  **/
#define ID_LAYR        MAKE_ID('L','A','Y','R')
#define ID_PNTS        MAKE_ID('P','N','T','S')
#define ID_VMAP        MAKE_ID('V','M','A','P')
#define ID_POLS        MAKE_ID('P','O','L','S')


Can anyone explain how these work?

Anonymous

Quote:This is part of what is confusing me. Why do they have the Tag_Id's written in this binary file as regular strings?

The reason I need this so bad is because it would save alot of loading time in my games. Not to mention that this format saves the specular values, transparency, vertex colors, etc... That, and I wont have to create the models in modeler, take them into layout, animate them, save each animation frame as a seperate object, send them back to modeler and save each one as a seperate Wavefront(.OBJ) file. It's a ton of work.


.LWO file Wrote:FORM LWO2TAGS Face_1 Face_2 Face_3 LAYR  PNTS `¿À ¿À ¿À ?À ¿À ¿À ?À ¿À ?À ¿À ¿À ?À ¿À ?À ¿À ?À ?À ¿À ?À ?À ?À ¿À ?À ?À BBOX ¿À ¿À ¿À ?À ?À ?À POLS dFACE                                             PTAG 4SURF                
VMAD ¾TXUV Texture  ?€  ?€  ?€  ?€ ?€   ?€  ?€    ?€  ?€   ?€  ?€ ?€     ?€  ?€  ?€   ?€  ?€ ?€    ?€   ?€  ?€  ?€ ?€   ?€   ?€   ?€  ?€  ?€ ?€  ?€ 
?€ 

?€  ?€  ?€  ?€ ?€


Also, I have a C++ object loader that came with LW-SDK, but it has these #Define things, and I have no idea of how they work.

Code:
#define MAKE_ID(a,b,c,d)    \
    ((unsigned long) (a)<<24 | (unsigned long) (b)<<16 | \
     (unsigned long) (c)<<8 | (unsigned long) (d))

/* Universal IFF identifiers */

#define ID_FORM        MAKE_ID('F','O','R','M')
#define ID_LWO2        MAKE_ID('L','W','O','2')

/**  PRIMARY CHUNK ID  **/
#define ID_LAYR        MAKE_ID('L','A','Y','R')
#define ID_PNTS        MAKE_ID('P','N','T','S')
#define ID_VMAP        MAKE_ID('V','M','A','P')
#define ID_POLS        MAKE_ID('P','O','L','S')


Can anyone explain how these work?


sure, they just putting the ascii data into a 4 byte thingy. i was talking about how you could shr to get individual numbers. well that is SHL'ing, and logical OR'ing (adding) them together. all thats doing is making a 4byte thing you can just slap down in one piece.

the basic equiv would be like

#define ID_POLS MAKE_ID('P','O','L','S')

put #1,, ID_POLS 'would put POLS string in binary file



they probably use strings just for ease of use
I think sample code makes it easier to understand.

Garvan


Code:
#define MAKE_ID(a,b,c,d) CLNG(ASC(a)) shl 24 OR CLNG(ASC(b)) shl 16 OR CLNG(ASC(c)) shl 8 OR CLNG(ASC(d))
#define ID_LAYR      MAKE_ID("L","A","Y","R")

PRINT CLNG(ASC("L")) shl 24 OR CLNG(ASC("A")) shl 16 OR CLNG(ASC("Y")) shl 8 OR CLNG(ASC("R"))
PRINT ID_LAYR
SLEEP
I think you can fix the problem easy by changing your code like this:
Code:
DO
   i = i + 1
   Get #1, i, Chunk.Tag

   If Chunk.Tag = "POLY" THEN
      'Get #1, i, Chunk    <---change this to
      Get #1, i, Chunk.Tag
      Get #1, i, Chunk.tLen

       Print Chunk.Tag
       Print Chunk. tLen
   End If
LOOP

Its only when a string is part of a UDT and you read the hole UDT, that it reads the extra zero byte... Correct me if Im wrong, but this is what I found out after some testing...
Can anyone show me an example of how to extract the values from the file? I'm not asking anyone to do the work for me because I really need to learn how, but I still get it. I just need a small example. The C++ file doesn't help me at all. It looks like this guy is using some really advanced C++ stuff, which I know nothing about.

I tried a bunch of different things, but nothing was even close, so I won't bother to post it.

Thanks, everyone. Wink
Pages: 1 2