aaaaa
This commit is contained in:
		
							parent
							
								
									37cdc242d9
								
							
						
					
					
						commit
						4cf895656d
					
				|  | @ -7,7 +7,14 @@ import ( | |||
| func main() { | ||||
| 	stl := stl2gltf.Load("D:\\src\\go\\stl2gltf\\example\\0c448109-7ac9-4f6d-aaf6-ce6bb744032f.stl") | ||||
| 	// log.Println(stl)
 | ||||
| 
 | ||||
| 	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")
 | ||||
| 	// // log.Println(stl)
 | ||||
| 	// 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")
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
							
								
								
									
										76
									
								
								convert.go
								
								
								
								
							
							
						
						
									
										76
									
								
								convert.go
								
								
								
								
							|  | @ -41,8 +41,8 @@ func Convert(stl STL, outFile string) { | |||
| 	normalBuf = padding(normalBuf) | ||||
| 	// 写入索引
 | ||||
| 	for i := range stl.TriangleNum * 3 { | ||||
| 		buf := make([]byte, 2) | ||||
| 		binary.LittleEndian.PutUint16(buf, uint16(i)) | ||||
| 		buf := make([]byte, 4) | ||||
| 		binary.LittleEndian.PutUint32(buf, uint32(i)) | ||||
| 		indexBuf = append(indexBuf, buf...) | ||||
| 	} | ||||
| 	indexBuf = padding(indexBuf) | ||||
|  | @ -50,70 +50,72 @@ func Convert(stl STL, outFile string) { | |||
| 	log.Println(len(positionBuf), len(normalBuf), len(indexBuf)) | ||||
| 
 | ||||
| 	allData := make([]byte, 0) | ||||
| 	allData = append(allData, positionBuf...) | ||||
| 	allData = append(allData, normalBuf...) | ||||
| 	allData = append(allData, indexBuf...) | ||||
| 	// allData = append(allData, normalBuf...)
 | ||||
| 	allData = append(allData, positionBuf...) | ||||
| 
 | ||||
| 	base := base64.StdEncoding.EncodeToString(allData) | ||||
| 
 | ||||
| 	attributes := make(map[string]int, 0) | ||||
| 	attributes["POSITION"] = 0 | ||||
| 	attributes["NORMAL"] = 1 | ||||
| 	attributes["POSITION"] = 1 | ||||
| 	// 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: 2, Mode: 4}}}}, | ||||
| 		Meshes:  []Mesh{{Primitives: []Primitive{{Attributes: attributes, Indices: 0, Mode: 4}}}}, | ||||
| 		Buffers: []Buffer{{Uri: fmt.Sprintf("data:application/gltf-buffer;base64,%s", base), ByteLength: len(allData)}}, | ||||
| 		BufferViews: []BufferView{ | ||||
| 			// position
 | ||||
| 			{ | ||||
| 				Buffer:     0, | ||||
| 				ByteOffset: 0, | ||||
| 				ByteLength: len(positionBuf), | ||||
| 				Target:     34962, | ||||
| 			}, | ||||
| 			// normal
 | ||||
| 			{ | ||||
| 				Buffer:     0, | ||||
| 				ByteOffset: len(positionBuf), | ||||
| 				ByteLength: len(normalBuf), | ||||
| 				Target:     34962, | ||||
| 			}, | ||||
| 			// index
 | ||||
| 			{ | ||||
| 				Buffer:     0, | ||||
| 				ByteOffset: len(positionBuf) + len(normalBuf), | ||||
| 				ByteOffset: 0, | ||||
| 				ByteLength: len(indexBuf), | ||||
| 				Target:     34963, | ||||
| 			}, | ||||
| 			// normal
 | ||||
| 			// {
 | ||||
| 			// 	Buffer:     0,
 | ||||
| 			// 	ByteOffset: len(indexBuf),
 | ||||
| 			// 	ByteLength: len(normalBuf),
 | ||||
| 			// 	Target:     34962,
 | ||||
| 			// },
 | ||||
| 			// position
 | ||||
| 			{ | ||||
| 				Buffer:     0, | ||||
| 				ByteOffset: len(indexBuf), | ||||
| 				// ByteOffset: len(indexBuf) + len(normalBuf),
 | ||||
| 				ByteLength: len(positionBuf), | ||||
| 				Target:     34962, | ||||
| 			}, | ||||
| 		}, | ||||
| 		Accessors: []Accessor{ | ||||
| 			{ | ||||
| 				BufferView:    0, | ||||
| 				ByteOffset:    0, | ||||
| 				ComponentType: 5126, | ||||
| 				Type:          "VEC3", | ||||
| 				Count:         len(positionBuf) / 12, | ||||
| 				Max:           stl.Max, | ||||
| 				Min:           stl.Min, | ||||
| 				ComponentType: 5125, | ||||
| 				Type:          "SCALAR", | ||||
| 				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, | ||||
| 				ByteOffset:    0, | ||||
| 				ComponentType: 5126, | ||||
| 				Type:          "VEC3", | ||||
| 				Count:         int(stl.TriangleNum), | ||||
| 				// Max:           []float32{1, 1, 1},
 | ||||
| 				// Min:           []float32{-1, -1, -1},
 | ||||
| 			}, | ||||
| 			{ | ||||
| 				BufferView:    2, | ||||
| 				ByteOffset:    0, | ||||
| 				ComponentType: 5123, | ||||
| 				Type:          "SCALAR", | ||||
| 				Count:         stl.TriangleNum, | ||||
| 				Count:         len(positionBuf) / 12, | ||||
| 				Max:           stl.Max, | ||||
| 				Min:           stl.Min, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  |  | |||
|  | @ -0,0 +1,167 @@ | |||
| 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 | ||||
| } | ||||
							
								
								
									
										33
									
								
								data.go
								
								
								
								
							
							
						
						
									
										33
									
								
								data.go
								
								
								
								
							|  | @ -1,10 +1,26 @@ | |||
| package stl2gltf | ||||
| 
 | ||||
| import "encoding/binary" | ||||
| 
 | ||||
| // Triangle 50B
 | ||||
| type Triangle struct { | ||||
| 	Normal    []byte // 4 * 3     12
 | ||||
| 	Position  []byte // 4 * 3 * 3 36
 | ||||
| 	Attribute []byte // 2         02
 | ||||
| 
 | ||||
| 	XYZ []float32 | ||||
| } | ||||
| 
 | ||||
| func (t Triangle) EuqalsPosition(position []byte) bool { | ||||
| 	x1 := binary.LittleEndian.Uint32(position[:4]) | ||||
| 	y1 := binary.LittleEndian.Uint32(position[4:8]) | ||||
| 	z1 := binary.LittleEndian.Uint32(position[8:12]) | ||||
| 
 | ||||
| 	x2 := binary.LittleEndian.Uint32(t.Position[:4]) | ||||
| 	y2 := binary.LittleEndian.Uint32(t.Position[4:8]) | ||||
| 	z2 := binary.LittleEndian.Uint32(t.Position[8:12]) | ||||
| 
 | ||||
| 	return x1 == x2 && y1 == y2 && z1 == z2 | ||||
| } | ||||
| 
 | ||||
| type STL struct { | ||||
|  | @ -16,6 +32,23 @@ type STL struct { | |||
| 	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 { | ||||
| 	Version string `json:"version"` | ||||
| } | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										68
									
								
								load.go
								
								
								
								
							
							
						
						
									
										68
									
								
								load.go
								
								
								
								
							|  | @ -70,3 +70,71 @@ func Load(filePath string) (stl 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