Sun, 25 Jul 2021 16:29:08 +0300
stuff
3 | 1 | /* |
2 | * LDForge: LDraw parts authoring CAD | |
24 | 3 | * Copyright (C) 2013 - 2020 Teemu Piippo |
3 | 4 | * |
5 | * This program is free software: you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation, either version 3 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | #include "model.h" | |
20 | #include "parser.h" | |
14 | 21 | #include "linetypes/comment.h" |
22 | #include "linetypes/conditionaledge.h" | |
23 | #include "linetypes/edge.h" | |
24 | #include "linetypes/errorline.h" | |
25 | #include "linetypes/metacommand.h" | |
26 | #include "linetypes/object.h" | |
15
9e18ec63eec3
split quadrilateral and triangle into their own source files
Teemu Piippo <teemu@hecknology.net>
parents:
14
diff
changeset
|
27 | #include "linetypes/quadrilateral.h" |
14 | 28 | #include "linetypes/subfilereference.h" |
15
9e18ec63eec3
split quadrilateral and triangle into their own source files
Teemu Piippo <teemu@hecknology.net>
parents:
14
diff
changeset
|
29 | #include "linetypes/triangle.h" |
3 | 30 | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
31 | struct BodyParseError |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
32 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
33 | QString message; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
34 | }; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
35 | |
3 | 36 | /* |
37 | * Constructs an LDraw parser | |
38 | */ | |
39 | Parser::Parser(QIODevice& device, QObject* parent) : | |
40 | QObject {parent}, | |
41 | device {device} {} | |
42 | ||
43 | /* | |
44 | * Reads a single line from the device. | |
45 | */ | |
46 | QString Parser::readLine() | |
47 | { | |
48 | return QString::fromUtf8(this->device.readLine()).trimmed(); | |
49 | } | |
50 | ||
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
51 | static const QMap<QString, LDHeader::FileType> typeStrings { |
3 | 52 | {"Part", LDHeader::Part}, |
53 | {"Subpart", LDHeader::Subpart}, | |
54 | {"Shortcut", LDHeader::Shortcut}, | |
55 | {"Primitive", LDHeader::Primitive}, | |
56 | {"8_Primitive", LDHeader::Primitive_8}, | |
57 | {"48_Primitive", LDHeader::Primitive_48}, | |
58 | {"Configuration", LDHeader::Configuration}, | |
59 | }; | |
60 | ||
61 | /* | |
62 | * Parses a single line of the header. | |
63 | * Possible parse results: | |
64 | * · ParseSuccess: the header line was parsed successfully. | |
65 | * · ParseFailure: the header line was parsed incorrectly and needs to be handled otherwise. | |
66 | * · StopParsing: the line does not belong in the header and header parsing needs to stop. | |
67 | */ | |
68 | Parser::HeaderParseResult Parser::parseHeaderLine( | |
69 | LDHeader& header, | |
70 | Winding& winding, | |
71 | const QString& line | |
72 | ) { | |
73 | if (line.isEmpty()) | |
74 | { | |
75 | return ParseSuccess; | |
76 | } | |
77 | else if (not line.startsWith("0") or line.startsWith("0 //")) | |
78 | { | |
79 | return StopParsing; | |
80 | } | |
81 | else if (line.startsWith("0 !LDRAW_ORG ")) | |
82 | { | |
83 | QStringList tokens = line | |
84 | .mid(strlen("0 !LDRAW_ORG ")) | |
105
6ca6e8c647d4
added preview layer code and fixed build warnings
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
85 | .split(" ", Qt::SkipEmptyParts); |
3 | 86 | if (not tokens.isEmpty()) |
87 | { | |
88 | QString partTypeString = tokens[0]; | |
89 | // Anything that enters LDForge becomes unofficial in any case if saved. | |
90 | // Therefore we don't need to give the Unofficial type any special | |
91 | // consideration. | |
92 | if (partTypeString.startsWith("Unofficial_")) | |
93 | partTypeString = partTypeString.mid(strlen("Unofficial_")); | |
5 | 94 | header.type = typeStrings.value(partTypeString, LDHeader::Part); |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
95 | header.qualfiers = {}; |
3 | 96 | if (tokens.contains("Alias")) |
97 | header.qualfiers |= LDHeader::Alias; | |
98 | if (tokens.contains("Physical_Color")) | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
99 | header.qualfiers |= LDHeader::PhysicalColour; |
3 | 100 | if (tokens.contains("Flexible_Section")) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
101 | header.qualfiers |= LDHeader::FlexibleSection; |
3 | 102 | return ParseSuccess; |
103 | } | |
104 | else | |
105 | { | |
106 | return ParseFailure; | |
107 | } | |
108 | } | |
109 | else if (line == "0 BFC CERTIFY CCW") | |
110 | { | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
111 | winding = Anticlockwise; |
3 | 112 | return ParseSuccess; |
113 | } | |
114 | else if (line == "0 BFC CERTIFY CW") | |
115 | { | |
116 | winding = Clockwise; | |
117 | return ParseSuccess; | |
118 | } | |
119 | else if (line == "0 BFC NOCERTIFY") | |
120 | { | |
121 | winding = NoWinding; | |
122 | return ParseSuccess; | |
123 | } | |
124 | else if (line.startsWith("0 !HISTORY ")) | |
125 | { | |
126 | static const QRegExp historyRegexp { | |
127 | R"(0 !HISTORY\s+(\d{4}-\d{2}-\d{2})\s+)" | |
128 | R"((\{[^}]+|\[[^]]+)[\]}]\s+(.+))" | |
129 | }; | |
130 | if (historyRegexp.exactMatch(line)) | |
131 | { | |
132 | QString dateString = historyRegexp.capturedTexts().value(1); | |
133 | QString authorWithPrefix = historyRegexp.capturedTexts().value(2); | |
134 | QString description = historyRegexp.capturedTexts().value(3); | |
135 | LDHeader::HistoryEntry historyEntry; | |
136 | historyEntry.date = QDate::fromString(dateString, Qt::ISODate); | |
137 | historyEntry.description = description; | |
138 | ||
139 | if (authorWithPrefix[0] == '{') | |
140 | historyEntry.author = authorWithPrefix + "}"; | |
141 | else | |
142 | historyEntry.author = authorWithPrefix.mid(1); | |
143 | ||
144 | header.history.append(historyEntry); | |
145 | return ParseSuccess; | |
146 | } | |
147 | else | |
148 | { | |
149 | return ParseFailure; | |
150 | } | |
151 | } | |
152 | else if (line.startsWith("0 Author: ")) | |
153 | { | |
154 | header.author = line.mid(strlen("0 Author: ")); | |
155 | return ParseSuccess; | |
156 | } | |
157 | else if (line.startsWith("0 Name: ")) | |
158 | { | |
159 | header.name = line.mid(strlen("0 Name: ")); | |
160 | return ParseSuccess; | |
161 | } | |
162 | else if (line.startsWith("0 !HELP ")) | |
163 | { | |
164 | if (not header.help.isEmpty()) | |
165 | header.help += "\n"; | |
166 | header.help += line.mid(strlen("0 !HELP ")); | |
167 | return ParseSuccess; | |
168 | } | |
169 | else if (line.startsWith("0 !KEYWORDS ")) | |
170 | { | |
171 | if (not header.keywords.isEmpty()) | |
172 | header.keywords += "\n"; | |
173 | header.keywords += line.mid(strlen("0 !KEYWORDS ")); | |
174 | return ParseSuccess; | |
175 | } | |
176 | else if (line.startsWith("0 !CATEGORY ")) | |
177 | { | |
178 | header.category = line.mid(strlen("0 !CATEGORY ")); | |
179 | return ParseSuccess; | |
180 | } | |
181 | else if (line.startsWith("0 !CMDLINE ")) | |
182 | { | |
183 | header.cmdline = line.mid(strlen("0 !CMDLINE ")); | |
184 | return ParseSuccess; | |
185 | } | |
186 | else if (line.startsWith("0 !LICENSE Redistributable under CCAL version 2.0")) | |
187 | { | |
188 | header.license = LDHeader::CaLicense; | |
189 | return ParseSuccess; | |
190 | } | |
191 | else if (line.startsWith("0 !LICENSE Not redistributable")) | |
192 | { | |
193 | header.license = LDHeader::NonCaLicense; | |
194 | return ParseSuccess; | |
195 | } | |
196 | else | |
197 | { | |
198 | return ParseFailure; | |
199 | } | |
200 | } | |
201 | ||
202 | /* | |
203 | * Parses the header from the device given at construction and returns | |
204 | * the resulting header structure. | |
205 | */ | |
206 | LDHeader Parser::parseHeader(Winding& winding) | |
207 | { | |
208 | LDHeader header = {}; | |
209 | if (not this->device.atEnd()) | |
210 | { | |
211 | // Parse the description | |
212 | QString descriptionLine = this->readLine(); | |
213 | if (descriptionLine.startsWith("0 ")) | |
214 | { | |
215 | header.description = descriptionLine.mid(strlen("0 ")).trimmed(); | |
216 | // Parse the rest of the header | |
217 | while (not this->device.atEnd()) | |
218 | { | |
219 | const QString& line = this->readLine(); | |
220 | auto result = parseHeaderLine(header, winding, line); | |
221 | if (result == ParseFailure) | |
222 | { | |
223 | // Failed to parse this header line, add it as a comment into the body later. | |
224 | this->bag.append(line); | |
225 | } | |
226 | else if (result == StopParsing) | |
227 | { | |
228 | // Header parsing stops, add this line to the body. | |
229 | this->bag.append(line); | |
230 | break; | |
231 | } | |
232 | } | |
233 | } | |
234 | else | |
235 | { | |
236 | this->bag.append(descriptionLine); | |
237 | } | |
238 | } | |
239 | return header; | |
240 | } | |
241 | ||
242 | /** | |
243 | * @brief Parses the model body into the given model. | |
244 | * @param editor Handle to model edit context | |
245 | */ | |
246 | void Parser::parseBody(Model::EditContext& editor) | |
247 | { | |
248 | bool invertNext = false; | |
249 | while (not this->device.atEnd()) | |
250 | this->bag.append(this->readLine()); | |
251 | for (const QString& line : this->bag) | |
252 | { | |
253 | if (line == "0 BFC INVERTNEXT" or line == "0 BFC CERTIFY INVERTNEXT") | |
254 | { | |
255 | invertNext = true; | |
256 | continue; | |
257 | } | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
258 | std::unique_ptr<ldraw::Object> object = parseFromString(line); |
26 | 259 | auto id = editor.append(std::move(object)); |
3 | 260 | if (invertNext) |
261 | { | |
26 | 262 | editor.invertObject(id); |
3 | 263 | } |
264 | invertNext = false; | |
265 | } | |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
266 | // Test quadrilateral splitting by splitting all the quadrilaterals |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
267 | QVector<ldraw::quadrilateralid_t> quadrilateral_ids; |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
268 | for (int i = 0; i < editor.model().size(); i += 1) |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
269 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
270 | const ldraw::id_t id = editor.model().resolve(editor.model().index(i)); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
271 | const ldraw::quadrilateralid_t quad_id = editor.model().checkType<ldraw::Quadrilateral>(id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
272 | if (not(quad_id == ldraw::NULL_ID)) |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
273 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
274 | quadrilateral_ids.push_back(quad_id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
275 | } |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
276 | } |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
277 | for (const ldraw::quadrilateralid_t id : quadrilateral_ids) |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
278 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
279 | ldraw::splitQuadrilateral(editor, id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
280 | } |
3 | 281 | } |
282 | ||
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
283 | static ldraw::Color colorFromString(const QString& colorString) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
284 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
285 | bool colorSucceeded; |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
286 | const ldraw::Color color = {colorString.toInt(&colorSucceeded)}; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
287 | if (colorSucceeded) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
288 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
289 | return color; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
290 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
291 | else |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
292 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
293 | throw BodyParseError{"colour was not an integer value"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
294 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
295 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
296 | |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
297 | static glm::vec3 vertexFromStrings( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
298 | const QStringList& tokens, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
299 | const int startingPosition) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
300 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
301 | bool ok_x; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
302 | const float x = tokens[startingPosition].toFloat(&ok_x); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
303 | bool ok_y; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
304 | const float y = tokens[startingPosition + 1].toFloat(&ok_y); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
305 | bool ok_z; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
306 | const float z = tokens[startingPosition + 2].toFloat(&ok_z); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
307 | if (not ok_x or not ok_y or not ok_z) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
308 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
309 | throw BodyParseError{"vertex contained illegal co-ordinates"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
310 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
311 | return {x, y, z}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
312 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
313 | |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
314 | static glm::mat4 matrixFromStrings(const QStringList& tokens, const int startingPosition, const int positionStartingIndex) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
315 | { |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
316 | glm::mat4 result = glm::mat4{1}; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
317 | for (int i = 0; i < 9; i += 1) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
318 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
319 | const int row = i / 3; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
320 | const int column = i % 3; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
321 | const int index = i + startingPosition; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
322 | if (index >= tokens.size()) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
323 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
324 | throw BodyParseError{"too few tokens available"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
325 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
326 | bool ok; |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
327 | // note that glm::mat4 is column-major |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
328 | result[column][row] = tokens[index].toFloat(&ok); |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
329 | if (not ok) |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
330 | { |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
331 | throw BodyParseError{"non-numeric values for matrix"}; |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
332 | } |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
333 | } |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
334 | for (int i = 0; i < 3; i += 1) |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
335 | { |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
336 | bool ok; |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
337 | const auto value = tokens[i + positionStartingIndex].toFloat(&ok); |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
338 | result[3][i] = value; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
339 | if (not ok) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
340 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
341 | throw BodyParseError{"non-numeric values for matrix"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
342 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
343 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
344 | return result; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
345 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
346 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
347 | static std::unique_ptr<ldraw::Object> parseType0Line( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
348 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
349 | const QStringList& tokens) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
350 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
351 | Q_UNUSED(tokens) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
352 | if (line.startsWith("0 //")) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
353 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
354 | return std::make_unique<ldraw::Comment>(line.mid(std::strlen("0 //")).simplified()); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
355 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
356 | else |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
357 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
358 | return std::make_unique<ldraw::MetaCommand>(line.mid(1).simplified()); |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
359 | } |
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
360 | } |
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
361 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
362 | static std::unique_ptr<ldraw::SubfileReference> parseType1Line( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
363 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
364 | const QStringList& tokens) |
5 | 365 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
366 | Q_UNUSED(line) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
367 | constexpr int colorPosition = 1; |
23
3387a84ddaba
fixed a pile of nonsense that caused subfiles to go haywire
Teemu Piippo <teemu@hecknology.net>
parents:
21
diff
changeset
|
368 | constexpr int positionPosition = 2; // 2..4 |
3387a84ddaba
fixed a pile of nonsense that caused subfiles to go haywire
Teemu Piippo <teemu@hecknology.net>
parents:
21
diff
changeset
|
369 | constexpr int transformPosition = 5; // 5..13 |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
370 | constexpr int namePosition = 14; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
371 | if (tokens.size() != 15) |
5 | 372 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
373 | throw BodyParseError{"wrong amount of tokens in a type-1 line"}; |
5 | 374 | } |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
375 | const ldraw::Color color = colorFromString(tokens[colorPosition]); |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
376 | const glm::mat4 transform = matrixFromStrings(tokens, transformPosition, positionPosition); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
377 | const QString& name = tokens[namePosition]; |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
378 | return std::make_unique<ldraw::SubfileReference>(transform, name, color); |
5 | 379 | } |
380 | ||
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
381 | template<typename T, int NumVertices> |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
382 | static std::unique_ptr<T> parsePolygon( |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
383 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
384 | const QStringList& tokens) |
5 | 385 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
386 | Q_UNUSED(line) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
387 | constexpr int colorPosition = 1; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
388 | auto vertexPosition = [](int n) { return 2 + 3*n; }; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
389 | if (tokens.size() != 2 + 3 * NumVertices) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
390 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
391 | throw BodyParseError{"wrong amount of tokens"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
392 | } |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
393 | const ldraw::Color color = colorFromString(tokens[colorPosition]); |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
394 | std::array<glm::vec3, NumVertices> vertices; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
395 | for (int i = 0; i < NumVertices; i += 1) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
396 | { |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
397 | vertices[unsigned_cast(i)] = vertexFromStrings(tokens, vertexPosition(i)); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
398 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
399 | return std::make_unique<T>(vertices, color); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
400 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
401 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
402 | std::unique_ptr<ldraw::Object> Parser::parseFromString(QString line) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
403 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
404 | line = line.simplified(); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
405 | try |
5 | 406 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
407 | const QStringList tokens = line.split(QRegExp{R"(\s+)"}); |
12 | 408 | if (tokens.empty() or tokens == QStringList{{""}}) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
409 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
410 | return std::make_unique<ldraw::Empty>(); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
411 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
412 | bool ok_code; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
413 | const int code = tokens[0].toInt(&ok_code); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
414 | if (not ok_code) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
415 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
416 | throw BodyParseError{"line type was not an integer"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
417 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
418 | switch (code) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
419 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
420 | case 0: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
421 | return parseType0Line(line, tokens); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
422 | case 1: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
423 | return parseType1Line(line, tokens); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
424 | case 2: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
425 | return parsePolygon<ldraw::Edge, 2>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
426 | case 3: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
427 | return parsePolygon<ldraw::Triangle, 3>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
428 | case 4: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
429 | return parsePolygon<ldraw::Quadrilateral, 4>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
430 | case 5: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
431 | return parsePolygon<ldraw::ConditionalEdge, 4>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
432 | default: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
433 | throw BodyParseError{utility::format("bad line type '%1'", code)}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
434 | } |
5 | 435 | } |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
436 | catch(const BodyParseError& error) |
5 | 437 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
438 | return std::make_unique<ldraw::ErrorLine>(line, error.message); |
5 | 439 | } |
440 | } |