So here is the first draft implementation of the importing of vertex positions.
This simple code is ready to use, the form is: (take-vertexes "test-file.obj")
(defmacro for-each-line (file line body) "Takes all liines from the file one by one." `(with-open-file (s ,file :direction :input) (let ((r nil) (eof-reached nil)) (loop while (not eof-reached) do (multiple-value-setq (,line eof-reached) (read-line s r)) (if ,line ,body))))) (defmacro read-vertex-data (v-line vertexes index &key count-only) "Reads three floats from the given line to the vertexes array starting with index. Index is increased and returned as a result afterwards." `(let* ((trimmed-line (string-trim '(#\Space #\Tab #\Newline) ,v-line))) (if (and (> (string-size-in-octets trimmed-line) 2) (char= #\v (char trimmed-line 0)) (or (char= #\Space (char trimmed-line 1)) (char= #\Tab (char trimmed-line 1)))) (let* ((trash1 t) (trash2 t) (val 0d0) (start-from 2)) ; skip "v " in the string (progn (multiple-value-setq (val start-from) (read-from-string trimmed-line trash1 trash2 :start start-from)) (if ,vertexes (setf (aref ,vertexes ,index) (coerce val 'double-float))) (incf ,index) (multiple-value-setq (val start-from) (read-from-string trimmed-line trash1 trash2 :start start-from)) (if ,vertexes (setf (aref ,vertexes ,index) (coerce val 'double-float))) (incf ,index) (multiple-value-setq (val start-from) (read-from-string trimmed-line trash1 trash2 :start start-from)) (if ,vertexes (setf (aref ,vertexes ,index) (coerce val 'double-float))) (incf ,index) ,index))))) (defun take-vertexes (file) "Takes all found vertexes from the given file to the given array. Returns the number of the read floats, not vertexes!" (let* ((count (let ((i 0)) (for-each-line file line (read-vertex-data line nil i)) i)) ; only count, no store (temporar-vertexes (make-array count :element-type 'double-float)) (actually-read-floats 0)) (for-each-line file line (read-vertex-data line temporar-vertexes actually-read-floats)) ; read+store temporar-vertexes))
http://github.com/death/towers/blob/master/towers.lisp has a different implementation, see LOAD-WF-OBJECT.
ReplyDeleteThank you, Xash! This info is really helpful. I tried to find it myself, but didn't succeed.
ReplyDelete