glb
This commit is contained in:
parent
7acdc03776
commit
d56044f05c
|
@ -1 +1,2 @@
|
|||
*.gltf
|
||||
*.glb
|
|
@ -7,10 +7,13 @@ import (
|
|||
func main() {
|
||||
stl := stl2gltf.Load("./example/0c448109-7ac9-4f6d-aaf6-ce6bb744032f.stl")
|
||||
stl2gltf.Convert(stl, "./example/0c448109-7ac9-4f6d-aaf6-ce6bb744032f.gltf")
|
||||
stl2gltf.ConvertGLB(stl, "./example/0c448109-7ac9-4f6d-aaf6-ce6bb744032f.glb")
|
||||
|
||||
stl = stl2gltf.Load("./example/1ec91891-c25a-4905-a79c-f3bc96045d37.stl")
|
||||
stl2gltf.Convert(stl, "./example/1ec91891-c25a-4905-a79c-f3bc96045d37.gltf")
|
||||
stl2gltf.ConvertGLB(stl, "./example/1ec91891-c25a-4905-a79c-f3bc96045d37.glb")
|
||||
|
||||
stl = stl2gltf.Load("./example/3ea057e5-1520-4898-a59c-f33a6c955bd7.stl")
|
||||
stl2gltf.Convert(stl, "./example/3ea057e5-1520-4898-a59c-f33a6c955bd7.gltf")
|
||||
stl2gltf.ConvertGLB(stl, "./example/3ea057e5-1520-4898-a59c-f33a6c955bd7.glb")
|
||||
}
|
||||
|
|
28
convert.go
28
convert.go
|
@ -49,7 +49,7 @@ func Convert(stl STL, outFile string) {
|
|||
}
|
||||
indexBuf = padding(indexBuf)
|
||||
|
||||
log.Println(len(positionBuf), len(normalBuf), len(indexBuf))
|
||||
log.Println("positions: ", len(positionBuf), " normals: ", len(normalBuf), " indices: ", len(indexBuf))
|
||||
|
||||
// concat
|
||||
allData := make([]byte, 0)
|
||||
|
@ -64,10 +64,10 @@ func Convert(stl STL, outFile string) {
|
|||
attributes["POSITION"] = 2
|
||||
|
||||
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}}}},
|
||||
Asset: Asset{Version: "2.0"},
|
||||
Scenes: []Scene{{Nodes: []int{0}}},
|
||||
Nodes: []Node{{Mesh: 0}},
|
||||
Meshes: []Mesh{{Primitives: []Primitive{{Attributes: attributes, Indices: 0, Mode: 4}}}},
|
||||
// ByteLength not length after base64
|
||||
Buffers: []Buffer{{Uri: fmt.Sprintf("data:application/gltf-buffer;base64,%s", base), ByteLength: len(allData)}},
|
||||
BufferViews: []BufferView{
|
||||
|
@ -83,14 +83,14 @@ func Convert(stl STL, outFile string) {
|
|||
Buffer: 0,
|
||||
ByteOffset: len(indexBuf),
|
||||
ByteLength: len(normalBuf),
|
||||
Target: 34962, // ARRAY_BUFFER int vertex
|
||||
Target: 34962, // ARRAY_BUFFER int vertex
|
||||
},
|
||||
// position
|
||||
{
|
||||
Buffer: 0,
|
||||
Buffer: 0,
|
||||
ByteOffset: len(indexBuf) + len(normalBuf),
|
||||
ByteLength: len(positionBuf),
|
||||
Target: 34962, // ARRAY_BUFFER int vertex
|
||||
Target: 34962, // ARRAY_BUFFER int vertex
|
||||
},
|
||||
},
|
||||
Accessors: []Accessor{
|
||||
|
@ -104,19 +104,19 @@ func Convert(stl STL, outFile string) {
|
|||
{
|
||||
BufferView: 1,
|
||||
ByteOffset: 0,
|
||||
ComponentType: 5126, // float
|
||||
ComponentType: 5126, // float
|
||||
Type: "VEC3",
|
||||
Count: stl.TriangleNum * 3, // 1 normal : 1 position
|
||||
Max: []float32{1, 1, 1}, // or cal from stl data
|
||||
Count: stl.TriangleNum * 3, // 1 normal : 1 position
|
||||
Max: []float32{1, 1, 1}, // or cal from stl data
|
||||
Min: []float32{-1, -1, -1},
|
||||
},
|
||||
{
|
||||
BufferView: 2,
|
||||
ByteOffset: 0,
|
||||
ComponentType: 5126, // float
|
||||
ComponentType: 5126, // float
|
||||
Type: "VEC3",
|
||||
Count: len(positionBuf) / 12,// xyz = 4x3; or stl.TriangleNum * 3
|
||||
Max: stl.Max, // cal from stl data
|
||||
Count: len(positionBuf) / 12, // xyz = 4x3; or stl.TriangleNum * 3
|
||||
Max: stl.Max, // cal from stl data
|
||||
Min: stl.Min,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
package stl2gltf
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func ConvertGLB(stl STL, outFile string) {
|
||||
// buf
|
||||
indexBuf := make([]byte, 0)
|
||||
normalBuf := make([]byte, 0)
|
||||
positionBuf := make([]byte, 0)
|
||||
|
||||
// padding each buffer part
|
||||
padding := func(buf []byte) []byte {
|
||||
for len(buf)%4 != 0 {
|
||||
buf = append(buf, 0x00)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
// positions to byte
|
||||
for i := range stl.TriangleNum {
|
||||
t := stl.Triangles[i]
|
||||
positionBuf = append(positionBuf, t.Position...)
|
||||
}
|
||||
positionBuf = padding(positionBuf)
|
||||
|
||||
// normals to byte
|
||||
for i := range stl.TriangleNum {
|
||||
t := stl.Triangles[i]
|
||||
// each position, write 3 times
|
||||
normalBuf = append(normalBuf, t.Normal...)
|
||||
normalBuf = append(normalBuf, t.Normal...)
|
||||
normalBuf = append(normalBuf, t.Normal...)
|
||||
}
|
||||
normalBuf = padding(normalBuf)
|
||||
// indices to byte
|
||||
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("positions: ", len(positionBuf), " normals: ", len(normalBuf), " indices: ", len(indexBuf))
|
||||
|
||||
// concat
|
||||
allData := make([]byte, 0)
|
||||
allData = append(allData, indexBuf...) // Indices: 0
|
||||
allData = append(allData, normalBuf...) // attributes["NORMAL"] = 1
|
||||
allData = append(allData, positionBuf...) // attributes["POSITION"] = 2
|
||||
|
||||
// base := base64.StdEncoding.EncodeToString(allData)
|
||||
attributes := make(map[string]int, 0)
|
||||
attributes["NORMAL"] = 1
|
||||
attributes["POSITION"] = 2
|
||||
|
||||
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}}}},
|
||||
// ByteLength not length after base64
|
||||
Buffers: []Buffer{{ByteLength: len(allData)}},
|
||||
BufferViews: []BufferView{
|
||||
// index
|
||||
{
|
||||
Buffer: 0,
|
||||
ByteOffset: 0,
|
||||
ByteLength: len(indexBuf),
|
||||
Target: 34963, // ELEMENT_ARRAY_BUFFER float indices
|
||||
},
|
||||
// normal
|
||||
{
|
||||
Buffer: 0,
|
||||
ByteOffset: len(indexBuf),
|
||||
ByteLength: len(normalBuf),
|
||||
Target: 34962, // ARRAY_BUFFER int vertex
|
||||
},
|
||||
// position
|
||||
{
|
||||
Buffer: 0,
|
||||
ByteOffset: len(indexBuf) + len(normalBuf),
|
||||
ByteLength: len(positionBuf),
|
||||
Target: 34962, // ARRAY_BUFFER int vertex
|
||||
},
|
||||
},
|
||||
Accessors: []Accessor{
|
||||
{
|
||||
BufferView: 0,
|
||||
ByteOffset: 0,
|
||||
ComponentType: 5125, // uint ; 5124 int will loss model parts
|
||||
Type: "SCALAR", // index
|
||||
Count: stl.TriangleNum * 3, // 1 index : 1 position
|
||||
},
|
||||
{
|
||||
BufferView: 1,
|
||||
ByteOffset: 0,
|
||||
ComponentType: 5126, // float
|
||||
Type: "VEC3",
|
||||
Count: stl.TriangleNum * 3, // 1 normal : 1 position
|
||||
Max: []float32{1, 1, 1}, // or cal from stl data
|
||||
Min: []float32{-1, -1, -1},
|
||||
},
|
||||
{
|
||||
BufferView: 2,
|
||||
ByteOffset: 0,
|
||||
ComponentType: 5126, // float
|
||||
Type: "VEC3",
|
||||
Count: len(positionBuf) / 12, // xyz = 4x3; or stl.TriangleNum * 3
|
||||
Max: stl.Max, // cal from stl data
|
||||
Min: stl.Min,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 生成glb
|
||||
outBuf := make([]byte, 0)
|
||||
|
||||
jsonChunkBuf := make([]byte, 0)
|
||||
|
||||
jsonData, err := json.Marshal(gltf)
|
||||
if err != nil {
|
||||
log.Println("marshal error: ", err.Error())
|
||||
return
|
||||
}
|
||||
jsonChunkBuf = binary.LittleEndian.AppendUint32(jsonChunkBuf, uint32(len(jsonData)))
|
||||
jsonChunkBuf = binary.LittleEndian.AppendUint32(jsonChunkBuf, uint32(0x4E4F534A))
|
||||
jsonChunkBuf = append(jsonChunkBuf, jsonData...)
|
||||
|
||||
binChunkBuf := make([]byte, 0)
|
||||
binChunkBuf = binary.LittleEndian.AppendUint32(binChunkBuf, uint32(len(allData)))
|
||||
binChunkBuf = binary.LittleEndian.AppendUint32(binChunkBuf, uint32(0x004E4942))
|
||||
binChunkBuf = append(binChunkBuf, allData...)
|
||||
|
||||
outBuf = binary.LittleEndian.AppendUint32(outBuf, uint32(0x46546C67))
|
||||
outBuf = binary.LittleEndian.AppendUint32(outBuf, uint32(2))
|
||||
outBuf = binary.LittleEndian.AppendUint32(outBuf, uint32(12+len(jsonChunkBuf)+len(binChunkBuf)))
|
||||
|
||||
outBuf = append(outBuf, jsonChunkBuf...)
|
||||
outBuf = append(outBuf, binChunkBuf...)
|
||||
|
||||
// output
|
||||
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(outBuf)
|
||||
}
|
Loading…
Reference in New Issue