dqst96444
dqst96444
2018-08-24 18:56
浏览 140
已采纳

在Golang中读取二进制.fbx文件

Unlike in other languages, I really couldn't figure out how to read a binary file into an array of bytes or just turn it into an ASCII-string, which puts me into quite a problem.

The code I've been using:

func TestFBX(fileName string) {
    file, err := os.Open(fileName)
    if (err != nil) {
        log.Fatal(err)
    }
    defer file.Close()

    var content []byte
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        text := []byte(scanner.Text())
        buf := bytes.NewReader(text)
        err := binary.Read(buf, binary.LittleEndian, &content)

        if (err != nil) {
            fmt.Println(err)
        }
    }

    fmt.Printf("%v", content)
    fmt.Println("")

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

What it does in the end is print out [ ], an empty slice. Now when I tried putting float64 or int32 instead of []byte it did print out different numbers but I still honestly don't get how to read the whole file and not just whatever number is there at the beginning.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douqiang7462
    douqiang7462 2019-02-26 00:20
    已采纳

    If you still interested in golang FBX reader here is my implementation https://github.com/o5h/fbx. Not well tested, but should work.

    Internally FBX have following structure:

    type Header [27]byte
    type FBX struct {
      Header *Header
      Top    *Node
      Nodes  []*Node
    }
    type Node struct {
      EndOffset       uint32
      NumProperties   uint32
      PropertyListLen uint32
      NameLen         uint8
      Name            string
      Properties      []*Property
      NestedNodes     []*Node
     }
     type Property struct {
      TypeCode byte
      Data     interface{}
     }
    

    Here is an usage example:

    f, _ := os.Open("cube.fbx")
    defer f.Close()
    fbxData, _ := fbx.ReadFrom(f)
    ibo := fbxData.Filter(fbx.FilterName("PolygonVertexIndex"))[0]
    fmt.Println(ibo)
    

    Output will be

    [0 2 -4 7 5 -5 4 1 -1 5 2 -2 2 7 -4 0 7 -5 0 1 -3 7 6 -6 4 5 -2 5 6 -3 2 6 -8 0 3 -8]
    

    Here is an example, how I get other attributes

    ibo := node.FilterName("PolygonVertexIndex")[0].Properties[0].AsInt32Slice()
    vbo := node.FilterName("Vertices")[0].Properties[0].AsFloat64Slice()
    normals := node.FilterName("Normals")[0].Properties[0].AsFloat64Slice()
    uvIndex := node.FilterName("UVIndex")[0].Properties[0].AsInt32Slice()
    uv := node.FilterName("UV")[0].Properties[0].AsFloat64Slice()
    
    numFaces := len(ibo) / 3
    for f := 0; f < numFaces; f++ {
        face := &Face{}
    
        index := f * 3
        a := int(ibo[index+0])
        b := int(ibo[index+1])
        c := int(ibo[index+2])*-1 - 1
    
        face.a.Position = getVec3(vbo, a)
        face.b.Position = getVec3(vbo, b)
        face.c.Position = getVec3(vbo, c)
    
        uva := int(uvIndex[index+0])
        uvb := int(uvIndex[index+1])
        uvc := int(uvIndex[index+2])
        face.a.UV = getVec2(uv, uva)
        face.b.UV = getVec2(uv, uvb)
        face.c.UV = getVec2(uv, uvc)
    
        face.a.Normal = getVec3(normals, f*3+0)
        face.b.Normal = getVec3(normals, f*3+1)
        face.c.Normal = getVec3(normals, f*3+2)
    
        faces[f] = face
    }
    
    type Vec3 struct {
        X, Y, Z float32
    }
    type Vec2 struct {
        X, Y float32
    }
    type Vertex struct {
        Position *Vec3
        Normal   *Vec3
        Color    *Vec3
        UV       *Vec2
    }
    
    type Face struct {
        a vertex.Vertex
        b vertex.Vertex
        c vertex.Vertex
    }
    
    func getVec3(data []float64, index int) *Vec3 {
        i := index * 3
        x := float32(data[i])
        y := float32(data[i+1])
        z := float32(data[i+2])
        return &Vec3{x, y, z}
    }
    
    点赞 评论
  • douzhaishan5462
    douzhaishan5462 2018-08-24 19:36

    You might just want ioutil.ReadFile(...)?:

    import "io/ioutil"
    
    // ...
    
    bs, err := ioutil.ReadFile("./myfile.fbx")
    if err != nil {
      panic(err) // TODO: handle error?
    }
    // now "bs" has all the bytes in the file...
    fmt.Printf("OK: read %d byte(s)
    ", len(bs))
    
    点赞 评论

相关推荐