package stl2gltf import ( "encoding/base64" "encoding/binary" "encoding/json" "fmt" "log" "os" ) func Convert2(stl STL2, 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 } uniquePositions := make([][3]uint32, 0) indices := make([]int16, len(stl.Positions)) for i := 0; i < len(stl.Positions); i++ { position := stl.Positions[i] // if in uniqt found := false for u, ut := range uniquePositions { if ut[0] == position[0] && ut[1] == position[1] && ut[2] == position[2] { // exist indices[i] = int16(u) found = true } } if !found { uniquePositions = append(uniquePositions, position) indices[i] = int16(len(uniquePositions) - 1) } } // 写入顶点 for _, ip := range uniquePositions { buf := make([]byte, 0) buf = binary.LittleEndian.AppendUint32(buf, uint32(ip[0])) buf = binary.LittleEndian.AppendUint32(buf, uint32(ip[1])) buf = binary.LittleEndian.AppendUint32(buf, uint32(ip[2])) positionBuf = append(positionBuf, buf...) } 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 indices { buf := make([]byte, 2) binary.LittleEndian.PutUint16(buf, uint16(i)) indexBuf = append(indexBuf, buf...) } indexBuf = padding(indexBuf) log.Println(len(positionBuf), len(normalBuf), len(indexBuf)) allData := make([]byte, 0) allData = append(allData, positionBuf...) allData = append(allData, indexBuf...) // allData = append(allData, normalBuf...) base := base64.StdEncoding.EncodeToString(allData) attributes := make(map[string]int, 0) attributes["POSITION"] = 0 // 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: 1, Mode: 4}}}}, Buffers: []Buffer{{Uri: fmt.Sprintf("data:application/gltf-buffer;base64,%s", base), ByteLength: len(allData)}}, BufferViews: []BufferView{ // index // normal // { // Buffer: 0, // ByteOffset: len(indexBuf), // ByteLength: len(normalBuf), // Target: 34962, // }, // position { Buffer: 0, ByteOffset: 0, // ByteOffset: len(indexBuf) + len(normalBuf), ByteLength: len(positionBuf), Target: 34962, }, { Buffer: 0, ByteOffset: len(positionBuf), ByteLength: len(indexBuf), Target: 34963, }, }, Accessors: []Accessor{ // { // BufferView: 1, // ByteOffset: 0, // ComponentType: 5126, // Type: "VEC3", // Count: int(stl.TriangleNum), // // Max: []float32{1, 1, 1}, // // Min: []float32{-1, -1, -1}, // }, { BufferView: 0, ByteOffset: 0, ComponentType: 5126, Type: "VEC3", Count: len(positionBuf) / 12, Max: f2i(stl.Max), Min: f2i(stl.Min), }, { BufferView: 1, ByteOffset: 0, ComponentType: 5123, Type: "SCALAR", Count: stl.TriangleNum, }, }, } 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) } func f2i(p []uint32) []float32 { a := make([]float32, len(p)) for i := 0; i < len(p); i++ { a[i] = float32(p[i]) } return a }