/
wavefront_parser.clj
109 lines (90 loc) · 2.53 KB
/
wavefront_parser.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
(ns wavefront-parser
(:require [clj-parser.core :refer :all])
(:import [clojure.java.io]))
(defrecord Vertex [x y z w])
(defrecord TextureCoord [u v w])
(defrecord Normal [x y z])
(defrecord FaceElement [vertex texture-coord normal])
(defrecord Face [elements])
(defn new-vertex [[x y z w]]
(Vertex. x y z w))
(defn new-tc [[u v w]]
(TextureCoord. u v w))
(defn new-normal [[x y z]]
(Normal. x y z))
(defn new-face-element [[v tc n]]
(FaceElement. v tc n))
(defn new-face [elements]
(Face. elements))
(def parse-vertex
(-> parse-any-number
(<* spaces)
(<=> parse-any-number)
(<* spaces)
(<=> parse-any-number)
(<* spaces)
(<=> (<|> parse-any-number (optional-value 1.0)))
(<f> new-vertex)))
(def parse-vline
(-> (parse-char \v)
(*> spaces)
(*> parse-vertex)))
(def parse-tc
(-> parse-any-number
(<* spaces)
(<=> parse-any-number)
(<* spaces)
(<=> (<|> parse-any-number (optional-value 0.0)))
(<f> new-tc)))
(def parse-tc-line
(-> (parse-char \v)
(*> (parse-char \t))
(*> spaces)
(*> parse-tc)))
(def parse-normal
(-> parse-any-number
(<* spaces)
(<=> parse-any-number)
(<* spaces)
(<=> parse-any-number)
(<f> new-normal)))
(def parse-normal-line
(-> (parse-char \v)
(*> (parse-char \n))
(*> spaces)
(*> parse-normal)))
(def parse-face-element
(-> (<|> parse-any-int (optional-value 0))
(<* (parse-char \/))
(<=> (<|> parse-any-int (optional-value 0)))
(<* (parse-char \/))
(<=> (<|> parse-any-int (optional-value 0)))
(<f> new-face-element)))
(def parse-face-line
(-> (parse-char \f)
(*> spaces)
(*> parse-face-element)
(<* spaces)
(<=> parse-face-element)
(<* spaces)
(<=> parse-face-element)
(<f> new-face)))
(def parse-wavefront-line
(-> parse-tc-line
(<|> parse-normal-line)
(<|> parse-vline)
(<|> parse-face-line)))
(defn parse-file [file-path]
(group-by class
(with-open [rdr (clojure.java.io/reader file-path)]
(reduce (fn [acc ln]
(if-let [parsed-val (extract-value (parse-wavefront-line ln))]
(conj acc parsed-val)
acc))
[] (line-seq rdr)))))
(comment
(parse-file "./examples/sample-wavefront.txt")
(parse-vline "v 3.2 2.01 -32.0")
(parse-tc-line "vt 0.555 0.000 0.555")
(parse-normal-line "vn 0.707 0.000 0.707")
(parse-face-line "f -2//-2 -1//-1 -3//-3"))