package stl2gltf import ( "encoding/base64" "encoding/binary" "encoding/json" "fmt" "log" "os" ) func Convert(stl STL, outFile string) { // buf indexBuf := make([]byte, 0) normalBuf := make([]byte, 0) positionBuf := make([]byte, 0) padding := func(buf []byte) []byte { log.Println("padding: ", len(buf)%4) for len(buf)%4 != 0 { log.Println("padding") buf = append(buf, 0x00) } return buf } // 写入顶点 for i := range stl.TriangleNum { t := stl.Triangles[i] positionBuf = append(positionBuf, t.Position...) } positionBuf = padding(positionBuf) // 写入法向量 for i := range stl.TriangleNum { t := stl.Triangles[i] normalBuf = append(normalBuf, t.Normal...) normalBuf = append(normalBuf, t.Normal...) normalBuf = append(normalBuf, t.Normal...) } normalBuf = padding(normalBuf) // 写入索引 for i := range stl.TriangleNum * 3 { buf := make([]byte, 4) binary.LittleEndian.PutUint32(buf, uint32(i)) indexBuf = append(indexBuf, buf...) } indexBuf = padding(indexBuf) log.Println(len(positionBuf), len(normalBuf), len(indexBuf)) allData := make([]byte, 0) allData = append(allData, indexBuf...) allData = append(allData, normalBuf...) allData = append(allData, positionBuf...) base := base64.StdEncoding.EncodeToString(allData) attributes := make(map[string]int, 0) attributes["POSITION"] = 2 attributes["NORMAL"] = 1 gltf := GLTF{ Asset: Asset{Version: "2.0"}, Scenes: []Scene{{Nodes: []int{0}}}, Nodes: []Node{{Mesh: 0}}, Meshes: []Mesh{{Primitives: []Primitive{{Attributes: attributes, Indices: 0, Mode: 4}}}}, Buffers: []Buffer{{Uri: fmt.Sprintf("data:application/gltf-buffer;base64,%s", base), ByteLength: len(allData)}}, BufferViews: []BufferView{ // index { Buffer: 0, ByteOffset: 0, ByteLength: len(indexBuf), Target: 34963, }, // normal { Buffer: 0, ByteOffset: len(indexBuf), ByteLength: len(normalBuf), Target: 34962, }, // position { Buffer: 0, // ByteOffset: len(indexBuf), ByteOffset: len(indexBuf) + len(normalBuf), ByteLength: len(positionBuf), Target: 34962, }, }, Accessors: []Accessor{ { BufferView: 0, ByteOffset: 0, ComponentType: 5125, Type: "SCALAR", Count: stl.TriangleNum * 3, }, { BufferView: 1, ByteOffset: 0, ComponentType: 5126, Type: "VEC3", Count: stl.TriangleNum * 3, Max: []float32{1, 1, 1}, Min: []float32{-1, -1, -1}, }, { BufferView: 2, ByteOffset: 0, ComponentType: 5126, Type: "VEC3", Count: len(positionBuf) / 12, Max: stl.Max, Min: stl.Min, }, }, } data, err := json.MarshalIndent(gltf, " ", " ") if err != nil { log.Println("marshal error: ", err.Error()) return } os.Remove(outFile) f, err := os.OpenFile(outFile, os.O_CREATE, os.ModePerm) if err != nil { log.Println("write file error: ", err.Error()) return } defer f.Close() f.Write(data) }