package main import ( "encoding/binary" "fmt" "math" ) // ReadSTL parses a binary STL byte slice into triangles. // Format: 80-byte header, uint32 count, N × 50-byte records // (12 bytes normal, 36 bytes vertices, 2 bytes attribute). func ReadSTL(data []byte) ([][3]Point, error) { if len(data) < 84 { return nil, fmt.Errorf("STL data too short (%d bytes, need at least 84)", len(data)) } count := binary.LittleEndian.Uint32(data[80:84]) expected := 84 + int(count)*50 debugLog("ReadSTL: %d bytes, header count=%d, expected=%d", len(data), count, expected) if len(data) < expected { return nil, fmt.Errorf("STL truncated: have %d bytes, need %d for %d triangles", len(data), expected, count) } triangles := make([][3]Point, 0, count) off := 84 for i := uint32(0); i < count; i++ { // Skip 12 bytes of face normal off += 12 var tri [3]Point for v := 0; v < 3; v++ { tri[v].X = float64(math.Float32frombits(binary.LittleEndian.Uint32(data[off:]))) tri[v].Y = float64(math.Float32frombits(binary.LittleEndian.Uint32(data[off+4:]))) tri[v].Z = float64(math.Float32frombits(binary.LittleEndian.Uint32(data[off+8:]))) off += 12 } // Skip 2-byte attribute off += 2 triangles = append(triangles, tri) } debugLog(" ReadSTL: parsed %d triangles", len(triangles)) return triangles, nil }