Reading(Writing) vertex list from MS3D with VB.Net

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
MeisterK
Posts: 66
Joined: Sat Feb 26, 2005 1:20 pm

Reading(Writing) vertex list from MS3D with VB.Net

Post by MeisterK »

Hello,

I know this is not directly about Irrlicht, but quite close and maybe someone can open my eyes.

I try to read(and later to write) the vertex list of an MS3D file. I found the make up of the format at http://astronomy.swin.edu.au/~pbourke/g ... ms3dspec.h

So far so good. My problem is that I'm unable to read the float values :-( I dare to insert my code in short in hope of a good hint:

Code: Select all

    Private Structure ms3d_vertex
        Dim flags As Byte ' SELECTED | SELECTED2 | HIDDEN
        Dim X, Y, Z As Single
        Dim boneId As Char
        Dim referenceCount As Byte
    End Structure

    Private Sub TestLoadMS3D
        Dim Header(9) As Byte 
        Const MSHeader As String = "MS3D000000"
        Dim fs As IO.FileStream
        Dim br As IO.BinaryReader
        Try
            fs = New IO.FileStream("c:\TestBox.ms3d", IO.FileMode.Open)
            fs.Read(Header, 0, 10)
            If System.Text.Encoding.ASCII.GetString(Header) = MSHeader Then
                Dim Version As Integer
                br = New IO.BinaryReader(fs)
                Version = br.ReadInt32
                If Version = 4 Then
                    Dim n, NoOfVertices As Int16
                    Dim dd As Double
                    Dim FloatB(3) As Byte
                    NoOfVertices = br.ReadInt16
                    Debug.WriteLine(String.Format("NoOfVertices = {0}", NoOfVertices))
                    For n = 0 To NoOfVertices - 1
                        Dim Vertex As ms3d_vertex
                        Vertex.flags = br.ReadByte
                        fs.Read(FloatB, 0, 4)

                        Vertex.X = br.ReadSingle ' <- This must be wrong
                        Vertex.Y = br.ReadSingle ' <- This must be wrong
                        Vertex.Z = br.ReadSingle ' <- This must be wrong

                        Vertex.boneId = br.ReadChar
                        Vertex.referenceCount = br.ReadByte
                        Debug.WriteLine(String.Format("Vertex {0}: {1}/ {2}/ {3}", n, Vertex.X, Vertex.Y, Vertex.Z))
                    Next
                Else
                    MessageBox.Show("Wrong version. Must be 4!")
                End If
            Else
                MessageBox.Show("Not a milkshape file!")
            End If
        Catch ex As Exception
            Stop
        Finally
            Try
                fs.Close()
            Catch
                ' nix
            End Try
        End Try
    End Sub
I know what the Vertex.X..Z values should be and they are completly different!

Thanks

Thorsten
[/code]
Fingers
Posts: 38
Joined: Thu Feb 10, 2005 10:17 am
Location: South Africa

Post by Fingers »

If I May ask ....

Code: Select all

                        Vertex.flags = br.ReadByte
                        fs.Read(FloatB, 0, 4)

                        Vertex.X = br.ReadSingle ' <- This must be wrong
Why are you reading from the binary reader, then the stream reader and then again from the binary reader ?? ..... To me that would cause a bit of confusion if the streamreader and binary reaer are accessing the same file ...

just my 2cents worth, might be worthwhile checking the effect in vb ... in c# I wouldn't mix the 2 readers ..
Guest

Post by Guest »

I don't know if there's a way to do this sort of stuff in VB.NET, but in C, you can load a float as bytes using something like:

union floatbytes {
float f;
char b[4];
};

then you read in 4 bytes from the file and store them in order in b[0]..b[3], and then you can just access f. (That's because a union makes its members share the same space).
MeisterK
Posts: 66
Joined: Sat Feb 26, 2005 1:20 pm

Post by MeisterK »

Hmm.

reviewing my code let me see, that " fs.Read(FloatB, 0, 4) " is not needed.

Code: Select all

                        Vertex.flags = br.ReadByte 

                     **   fs.Read(FloatB, 0, 4)  **

                        Vertex.X = br.ReadSingle ' <- This must be wrong 
Using a BinaryStream reader on a stream with mixed read operations should not make any problems. But to make sure I created a version with only a binary reader. Same result. The floats are still wrong :-(

Thorsten
MeisterK
Posts: 66
Joined: Sat Feb 26, 2005 1:20 pm

Post by MeisterK »

I've found the solution myself. Here it comes (if someone is interested in)

The problem seems to be with the boneId. According to the format I declared it as CHAR and read it from the stream unsing ReadChar.
But this command increases the position in the stream not by 1, but by 2! So all following readings were wrong.

The solution is easy: declare the boneId as byte:

Code: Select all

    Private Structure ms3d_vertex
        Dim flags As Byte ' SELECTED | SELECTED2 | HIDDEN
        Dim X, Y, Z As Single
         Dim boneId As Byte (!!!!)
        Dim referenceCount As Byte
    End Structure
And inside the For-Next-Loop:

Code: Select all

Vertex.boneId = br.ReadByte
In the end, the ReadSingle function was perfectly right!

Thorsten
MeisterK
Posts: 66
Joined: Sat Feb 26, 2005 1:20 pm

Post by MeisterK »

PS:

Because Windows is a Unicode system the ReadChar function takes two bytes from the stream, not one.
Post Reply