Skip to content

Instantly share code, notes, and snippets.

@jackrusher
Last active November 23, 2018 19:10
Show Gist options
  • Save jackrusher/8958272 to your computer and use it in GitHub Desktop.
Save jackrusher/8958272 to your computer and use it in GitHub Desktop.
A quick hack to load binary STL files using ztellman's gloss and pjstadig's nio library.
(ns stl-reader
(:require [nio.core :as nio])
(:use [gloss core io]))
(defcodec stl-codec
{:header (string :ascii :length 80)
:shape (repeated (ordered-map :normal [:float32-le :float32-le :float32-le]
:v1 [:float32-le :float32-le :float32-le]
:v2 [:float32-le :float32-le :float32-le]
:v3 [:float32-le :float32-le :float32-le]
:attr-count :uint16)
:prefix :uint32-le)})
(def stl-test (decode stl-codec (to-buf-seq (nio/mmap "some-file.stl"))))
;; OpenGL turned out to be painful in Java, so I also wrote a loader in Common Lisp
;; (a little longer because I didn't use a fancy DSL like gloss)
(ql:quickload "ieee-floats")
(use-package 'ieee-floats)
(defun read-uint-32 (in)
(let ((uint 0))
(dotimes (i 4)
(setf (ldb (byte 8 (* i 8)) uint) (read-byte in)))
uint))
(defun read-3d-vector (in)
(loop repeat 3 collect (ieee-floats:decode-float32 (read-uint-32 in))))
(defun read-binary-stl (in)
(file-position in 80) ;; useless header
(loop repeat (read-uint-32 in) collect
(let ((normal (read-3d-vector in))
(vertices (loop repeat 3 collect (read-3d-vector in))))
(file-position in (+ (file-position in) 2)) ;; skip!
`((:normal . ,normal) (:vertices . ,vertices)))))
(with-open-file (in #P"cube.stl" :element-type '(unsigned-byte 8))
(read-binary-stl in))
;; ...and a Racket version
;; (it turned out racket had the best OpenGL support)
(define (load-binary-stl in)
(define (bytes->3d-vector in)
(for/list [(v 3)] (floating-point-bytes->real (read-bytes 4 in))))
(read-bytes 80 in) ;; header junk
(let [(triangle-count (integer-bytes->integer (read-bytes 4 in) #f))]
(for/list [(t triangle-count)]
(let [(normal (bytes->3d-vector in))
(vertices (for/list [(v 3)] (bytes->3d-vector in)))]
(read-bytes 2 in) ;; eat the empty attrib mark
`((:normal . ,normal) (:vertices . ,vertices))))))
(call-with-input-file "cube.stl" load-binary-stl)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment