convert
This commit is contained in:
parent
4cf895656d
commit
6d0836d660
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
41
convert.go
41
convert.go
|
@ -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,
|
||||||
|
|
167
convert2.go
167
convert2.go
|
@ -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
17
data.go
|
@ -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
68
load.go
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue