47 lines
1.3 KiB
Go
47 lines
1.3 KiB
Go
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
|
||
}
|