This commit is contained in:
dengqn 2024-06-06 02:26:04 +08:00
parent 4cf895656d
commit 6d0836d660
8 changed files with 326 additions and 283 deletions

View File

@ -5,16 +5,12 @@ import (
) )
func main() { func main() {
stl := stl2gltf.Load("D:\\src\\go\\stl2gltf\\example\\0c448109-7ac9-4f6d-aaf6-ce6bb744032f.stl") stl := stl2gltf.Load("./example/0c448109-7ac9-4f6d-aaf6-ce6bb744032f.stl")
// log.Println(stl) stl2gltf.Convert(stl, "./example/0c448109-7ac9-4f6d-aaf6-ce6bb744032f.gltf")
stl2gltf.Convert(stl, "C:\\Users\\13040\\Downloads\\0c448109-7ac9-4f6d-aaf6-ce6bb744032f.gltf")
// stl = stl2gltf.Load("D:\\src\\go\\stl2gltf\\example\\1ec91891-c25a-4905-a79c-f3bc96045d37.stl") stl = stl2gltf.Load("./example/1ec91891-c25a-4905-a79c-f3bc96045d37.stl")
// // log.Println(stl) stl2gltf.Convert(stl, "./example/1ec91891-c25a-4905-a79c-f3bc96045d37.gltf")
// stl2gltf.Convert(stl, "C:\\Users\\13040\\Downloads\\1ec91891-c25a-4905-a79c-f3bc96045d37.gltf")
// stl = stl2gltf.Load("D:\\src\\go\\stl2gltf\\example\\3ea057e5-1520-4898-a59c-f33a6c955bd7.stl")
// // log.Println(stl)
// stl2gltf.Convert(stl, "C:\\Users\\13040\\Downloads\\3ea057e5-1520-4898-a59c-f33a6c955bd7.gltf")
stl = stl2gltf.Load("./example/3ea057e5-1520-4898-a59c-f33a6c955bd7.stl")
stl2gltf.Convert(stl, "./example/3ea057e5-1520-4898-a59c-f33a6c955bd7.gltf")
} }

View File

@ -51,14 +51,14 @@ func Convert(stl STL, outFile string) {
allData := make([]byte, 0) allData := make([]byte, 0)
allData = append(allData, indexBuf...) allData = append(allData, indexBuf...)
// allData = append(allData, normalBuf...) allData = append(allData, normalBuf...)
allData = append(allData, positionBuf...) allData = append(allData, positionBuf...)
base := base64.StdEncoding.EncodeToString(allData) base := base64.StdEncoding.EncodeToString(allData)
attributes := make(map[string]int, 0) attributes := make(map[string]int, 0)
attributes["POSITION"] = 1 attributes["POSITION"] = 2
// attributes["NORMAL"] = 1 attributes["NORMAL"] = 1
gltf := GLTF{ gltf := GLTF{
Asset: Asset{Version: "2.0"}, Asset: Asset{Version: "2.0"},
@ -75,17 +75,17 @@ func Convert(stl STL, outFile string) {
Target: 34963, Target: 34963,
}, },
// normal // normal
// {
// Buffer: 0,
// ByteOffset: len(indexBuf),
// ByteLength: len(normalBuf),
// Target: 34962,
// },
// position
{ {
Buffer: 0, Buffer: 0,
ByteOffset: len(indexBuf), ByteOffset: len(indexBuf),
// ByteOffset: len(indexBuf) + len(normalBuf), ByteLength: len(normalBuf),
Target: 34962,
},
// position
{
Buffer: 0,
// ByteOffset: len(indexBuf),
ByteOffset: len(indexBuf) + len(normalBuf),
ByteLength: len(positionBuf), ByteLength: len(positionBuf),
Target: 34962, Target: 34962,
}, },
@ -98,21 +98,20 @@ func Convert(stl STL, outFile string) {
Type: "SCALAR", Type: "SCALAR",
Count: stl.TriangleNum * 3, Count: stl.TriangleNum * 3,
}, },
// {
// BufferView: 1,
// ByteOffset: 0,
// ComponentType: 5126,
// Type: "VEC3",
// Count: int(stl.TriangleNum),
// // Max: []float32{1, 1, 1},
// // Min: []float32{-1, -1, -1},
// },
{ {
BufferView: 1, BufferView: 1,
ByteOffset: 0, ByteOffset: 0,
ComponentType: 5126, ComponentType: 5126,
Type: "VEC3", Type: "VEC3",
Count: int(stl.TriangleNum),
Max: []float32{1, 1, 1},
Min: []float32{-1, -1, -1},
},
{
BufferView: 2,
ByteOffset: 0,
ComponentType: 5126,
Type: "VEC3",
Count: len(positionBuf) / 12, Count: len(positionBuf) / 12,
Max: stl.Max, Max: stl.Max,
Min: stl.Min, Min: stl.Min,

View File

@ -1,167 +0,0 @@
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
}

17
data.go
View File

@ -32,23 +32,6 @@ type STL struct {
Min []float32 Min []float32
} }
type Triangle2 struct {
Normal []byte // 4 * 3 12
Position [][3]float32 // 4 * 3 * 3 36
Attribute []byte // 2 02
XYZ []float32
}
type STL2 struct {
Header string
TriangleNum int
Positions [][3]uint32
Max []uint32
Min []uint32
}
type Asset struct { type Asset struct {
Version string `json:"version"` Version string `json:"version"`
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

68
load.go
View File

@ -70,71 +70,3 @@ func Load(filePath string) (stl STL) {
return stl return stl
} }
func Load2(filePath string) (stl STL2) {
file, err := os.OpenFile(filePath, os.O_RDONLY, os.ModePerm)
if err != nil {
log.Panic("open file " + filePath + " error: " + err.Error())
}
headerBuf := make([]byte, 80)
file.Read(headerBuf)
triangleNumBuf := make([]byte, 4)
file.Read(triangleNumBuf)
stl.Header = string(headerBuf)
stl.TriangleNum = int(binary.LittleEndian.Uint32(triangleNumBuf))
stl.Positions = make([][3]uint32, 0)
max := []uint32{0, 0, 0}
min := []uint32{0, 0, 0}
for range stl.TriangleNum {
normalBuf := make([]byte, 4*3)
file.Read(normalBuf)
positionBuf := make([]byte, 4*3*3)
file.Read(positionBuf)
x := uint32(0)
y := uint32(0)
z := uint32(0)
for r := range 3 {
x1 := math.Float32frombits(binary.LittleEndian.Uint32(positionBuf[:4+(r*4)]))
y1 := math.Float32frombits(binary.LittleEndian.Uint32(positionBuf[(r * 4) : (r*4)+4]))
z1 := math.Float32frombits(binary.LittleEndian.Uint32(positionBuf[(r*4)+4 : (r*4)+8]))
// x = uint32(x1) * 10000 / 10000
// y = uint32(y1) * 10000 / 10000
// z = uint32(z1) * 10000 / 10000
x = uint32(x1) * 1 / 1
y = uint32(y1) * 1 / 1
z = uint32(z1) * 1 / 1
if max[0] < x {
max[0] = x
}
if max[1] < y {
max[1] = y
}
if max[2] < z {
max[2] = z
}
if min[0] > x {
min[0] = x
}
if min[1] > y {
min[1] = y
}
if min[2] > z {
min[2] = z
}
stl.Positions = append(stl.Positions, [3]uint32{x, y, z})
}
attributeBuf := make([]byte, 2)
file.Read(attributeBuf)
}
stl.Max = max
stl.Min = min
return stl
}