glb
This commit is contained in:
		
							parent
							
								
									7acdc03776
								
							
						
					
					
						commit
						d56044f05c
					
				|  | @ -1 +1,2 @@ | |||
| *.gltf | ||||
| *.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") | ||||
| } | ||||
|  |  | |||
							
								
								
									
										32
									
								
								convert.go
								
								
								
								
							
							
						
						
									
										32
									
								
								convert.go
								
								
								
								
							|  | @ -49,14 +49,14 @@ 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) | ||||
| 	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) | ||||
|  | @ -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,40 +83,40 @@ 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{ | ||||
| 			{ | ||||
| 				BufferView:    0, | ||||
| 				ByteOffset:    0, | ||||
| 				ComponentType: 5125,                // uint ;      5124 int will loss model parts  
 | ||||
| 				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
 | ||||
| 				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) | ||||
| } | ||||
							
								
								
									
										5
									
								
								data.go
								
								
								
								
							
							
						
						
									
										5
									
								
								data.go
								
								
								
								
							|  | @ -1,7 +1,5 @@ | |||
| package stl2gltf | ||||
| 
 | ||||
| import "encoding/binary" | ||||
| 
 | ||||
| // Triangle 50B
 | ||||
| type Triangle struct { | ||||
| 	Normal    []byte // 4 * 3     12
 | ||||
|  | @ -11,14 +9,13 @@ type Triangle struct { | |||
| 	XYZ []float32 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
| //        header     num
 | ||||
| //   |----80B------|-4B-|-----triangle1--------|--------triangle2-------|-----------...
 | ||||
| 
 | ||||
| //                    Normal(xyz) 4 x 3       position1       position2          position3         attribute
 | ||||
| //   each triangle: |--------12--------|--------12--------|--------12--------|--------12--------|---2-------|
 | ||||
| //  
 | ||||
| //
 | ||||
| //
 | ||||
| //
 | ||||
| //
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue