Sun, 24 Oct 2021 11:33:32 +0300
update
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 | ||
51 | /* | |
52 | * Parses a single line of the header. | |
53 | * Possible parse results: | |
54 | * · ParseSuccess: the header line was parsed successfully. | |
55 | * · ParseFailure: the header line was parsed incorrectly and needs to be handled otherwise. | |
56 | * · StopParsing: the line does not belong in the header and header parsing needs to stop. | |
57 | */ | |
58 | Parser::HeaderParseResult Parser::parseHeaderLine( | |
59 | LDHeader& header, | |
60 | Winding& winding, | |
61 | const QString& line | |
62 | ) { | |
63 | if (line.isEmpty()) | |
64 | { | |
65 | return ParseSuccess; | |
66 | } | |
67 | else if (not line.startsWith("0") or line.startsWith("0 //")) | |
68 | { | |
69 | return StopParsing; | |
70 | } | |
71 | else if (line.startsWith("0 !LDRAW_ORG ")) | |
72 | { | |
73 | QStringList tokens = line | |
74 | .mid(strlen("0 !LDRAW_ORG ")) | |
105
6ca6e8c647d4
added preview layer code and fixed build warnings
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
75 | .split(" ", Qt::SkipEmptyParts); |
3 | 76 | if (not tokens.isEmpty()) |
77 | { | |
78 | QString partTypeString = tokens[0]; | |
79 | // Anything that enters LDForge becomes unofficial in any case if saved. | |
80 | // Therefore we don't need to give the Unofficial type any special | |
81 | // consideration. | |
82 | if (partTypeString.startsWith("Unofficial_")) | |
83 | partTypeString = partTypeString.mid(strlen("Unofficial_")); | |
140 | 84 | header.type = headerTypeFromString(partTypeString); |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
85 | header.qualfiers = {}; |
3 | 86 | if (tokens.contains("Alias")) |
87 | header.qualfiers |= LDHeader::Alias; | |
88 | if (tokens.contains("Physical_Color")) | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
89 | header.qualfiers |= LDHeader::PhysicalColour; |
3 | 90 | if (tokens.contains("Flexible_Section")) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
91 | header.qualfiers |= LDHeader::FlexibleSection; |
3 | 92 | return ParseSuccess; |
93 | } | |
94 | else | |
95 | { | |
96 | return ParseFailure; | |
97 | } | |
98 | } | |
99 | else if (line == "0 BFC CERTIFY CCW") | |
100 | { | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
101 | winding = Anticlockwise; |
3 | 102 | return ParseSuccess; |
103 | } | |
104 | else if (line == "0 BFC CERTIFY CW") | |
105 | { | |
106 | winding = Clockwise; | |
107 | return ParseSuccess; | |
108 | } | |
109 | else if (line == "0 BFC NOCERTIFY") | |
110 | { | |
111 | winding = NoWinding; | |
112 | return ParseSuccess; | |
113 | } | |
114 | else if (line.startsWith("0 !HISTORY ")) | |
115 | { | |
116 | static const QRegExp historyRegexp { | |
117 | R"(0 !HISTORY\s+(\d{4}-\d{2}-\d{2})\s+)" | |
118 | R"((\{[^}]+|\[[^]]+)[\]}]\s+(.+))" | |
119 | }; | |
120 | if (historyRegexp.exactMatch(line)) | |
121 | { | |
122 | QString dateString = historyRegexp.capturedTexts().value(1); | |
123 | QString authorWithPrefix = historyRegexp.capturedTexts().value(2); | |
124 | QString description = historyRegexp.capturedTexts().value(3); | |
125 | LDHeader::HistoryEntry historyEntry; | |
126 | historyEntry.date = QDate::fromString(dateString, Qt::ISODate); | |
127 | historyEntry.description = description; | |
128 | ||
129 | if (authorWithPrefix[0] == '{') | |
130 | historyEntry.author = authorWithPrefix + "}"; | |
131 | else | |
132 | historyEntry.author = authorWithPrefix.mid(1); | |
133 | ||
134 | header.history.append(historyEntry); | |
135 | return ParseSuccess; | |
136 | } | |
137 | else | |
138 | { | |
139 | return ParseFailure; | |
140 | } | |
141 | } | |
142 | else if (line.startsWith("0 Author: ")) | |
143 | { | |
144 | header.author = line.mid(strlen("0 Author: ")); | |
145 | return ParseSuccess; | |
146 | } | |
147 | else if (line.startsWith("0 Name: ")) | |
148 | { | |
149 | header.name = line.mid(strlen("0 Name: ")); | |
150 | return ParseSuccess; | |
151 | } | |
152 | else if (line.startsWith("0 !HELP ")) | |
153 | { | |
154 | if (not header.help.isEmpty()) | |
155 | header.help += "\n"; | |
156 | header.help += line.mid(strlen("0 !HELP ")); | |
157 | return ParseSuccess; | |
158 | } | |
159 | else if (line.startsWith("0 !KEYWORDS ")) | |
160 | { | |
161 | if (not header.keywords.isEmpty()) | |
162 | header.keywords += "\n"; | |
163 | header.keywords += line.mid(strlen("0 !KEYWORDS ")); | |
164 | return ParseSuccess; | |
165 | } | |
166 | else if (line.startsWith("0 !CATEGORY ")) | |
167 | { | |
168 | header.category = line.mid(strlen("0 !CATEGORY ")); | |
169 | return ParseSuccess; | |
170 | } | |
171 | else if (line.startsWith("0 !CMDLINE ")) | |
172 | { | |
173 | header.cmdline = line.mid(strlen("0 !CMDLINE ")); | |
174 | return ParseSuccess; | |
175 | } | |
140 | 176 | else if (line.startsWith(LDHeader::caLicenseString)) |
3 | 177 | { |
178 | header.license = LDHeader::CaLicense; | |
179 | return ParseSuccess; | |
180 | } | |
140 | 181 | else if (line.startsWith(LDHeader::nonCaLicenseString)) |
3 | 182 | { |
183 | header.license = LDHeader::NonCaLicense; | |
184 | return ParseSuccess; | |
185 | } | |
186 | else | |
187 | { | |
188 | return ParseFailure; | |
189 | } | |
190 | } | |
191 | ||
192 | /* | |
193 | * Parses the header from the device given at construction and returns | |
194 | * the resulting header structure. | |
195 | */ | |
196 | LDHeader Parser::parseHeader(Winding& winding) | |
197 | { | |
198 | LDHeader header = {}; | |
199 | if (not this->device.atEnd()) | |
200 | { | |
201 | // Parse the description | |
202 | QString descriptionLine = this->readLine(); | |
203 | if (descriptionLine.startsWith("0 ")) | |
204 | { | |
205 | header.description = descriptionLine.mid(strlen("0 ")).trimmed(); | |
206 | // Parse the rest of the header | |
207 | while (not this->device.atEnd()) | |
208 | { | |
209 | const QString& line = this->readLine(); | |
210 | auto result = parseHeaderLine(header, winding, line); | |
211 | if (result == ParseFailure) | |
212 | { | |
213 | // Failed to parse this header line, add it as a comment into the body later. | |
214 | this->bag.append(line); | |
215 | } | |
216 | else if (result == StopParsing) | |
217 | { | |
218 | // Header parsing stops, add this line to the body. | |
219 | this->bag.append(line); | |
220 | break; | |
221 | } | |
222 | } | |
223 | } | |
224 | else | |
225 | { | |
226 | this->bag.append(descriptionLine); | |
227 | } | |
228 | } | |
229 | return header; | |
230 | } | |
231 | ||
232 | /** | |
233 | * @brief Parses the model body into the given model. | |
234 | * @param editor Handle to model edit context | |
235 | */ | |
236 | void Parser::parseBody(Model::EditContext& editor) | |
237 | { | |
238 | bool invertNext = false; | |
239 | while (not this->device.atEnd()) | |
240 | this->bag.append(this->readLine()); | |
241 | for (const QString& line : this->bag) | |
242 | { | |
144
5d73a6717321
Fix handling of "BFC INVERTNEXT" with multiple inner whitespaces
Teemu Piippo <teemu@hecknology.net>
parents:
141
diff
changeset
|
243 | // Some LDraw parts such as 53588.dat can contain "BFC INVERTNEXT" with multiple inner whitespaces. |
5d73a6717321
Fix handling of "BFC INVERTNEXT" with multiple inner whitespaces
Teemu Piippo <teemu@hecknology.net>
parents:
141
diff
changeset
|
244 | // So we need to pass the string through QString::simplified to catch these cases. |
5d73a6717321
Fix handling of "BFC INVERTNEXT" with multiple inner whitespaces
Teemu Piippo <teemu@hecknology.net>
parents:
141
diff
changeset
|
245 | const QString simplifiedLine = line.simplified(); |
5d73a6717321
Fix handling of "BFC INVERTNEXT" with multiple inner whitespaces
Teemu Piippo <teemu@hecknology.net>
parents:
141
diff
changeset
|
246 | if (simplifiedLine == "0 BFC INVERTNEXT" or simplifiedLine == "0 BFC CERTIFY INVERTNEXT") |
3 | 247 | { |
248 | invertNext = true; | |
249 | continue; | |
250 | } | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
251 | std::unique_ptr<ldraw::Object> object = parseFromString(line); |
26 | 252 | auto id = editor.append(std::move(object)); |
3 | 253 | if (invertNext) |
254 | { | |
26 | 255 | editor.invertObject(id); |
3 | 256 | } |
257 | invertNext = false; | |
258 | } | |
141 | 259 | /* |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
260 | // 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
|
261 | 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
|
262 | 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
|
263 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
264 | 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
|
265 | 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
|
266 | 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
|
267 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
268 | 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
|
269 | } |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
270 | } |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
271 | 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
|
272 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
273 | ldraw::splitQuadrilateral(editor, id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
274 | } |
141 | 275 | */ |
3 | 276 | } |
277 | ||
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
278 | static ldraw::Color colorFromString(const QString& colorString) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
279 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
280 | 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
|
281 | const ldraw::Color color = {colorString.toInt(&colorSucceeded)}; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
282 | if (colorSucceeded) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
283 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
284 | return color; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
285 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
286 | else |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
287 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
288 | throw BodyParseError{"colour was not an integer value"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
289 | } |
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 | |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
292 | static glm::vec3 vertexFromStrings( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
293 | const QStringList& tokens, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
294 | const int startingPosition) |
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 | bool ok_x; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
297 | const float x = tokens[startingPosition].toFloat(&ok_x); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
298 | bool ok_y; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
299 | const float y = tokens[startingPosition + 1].toFloat(&ok_y); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
300 | bool ok_z; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
301 | const float z = tokens[startingPosition + 2].toFloat(&ok_z); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
302 | 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
|
303 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
304 | throw BodyParseError{"vertex contained illegal co-ordinates"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
305 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
306 | return {x, y, z}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
307 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
308 | |
115 | 309 | static glm::mat4 matrixFromStrings( |
310 | const QStringList& tokens, | |
311 | const int startingPosition, | |
312 | const int positionStartingIndex) | |
8
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 | glm::mat4 result = glm::mat4{1}; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
315 | for (int i = 0; i < 9; i += 1) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
316 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
317 | const int row = i / 3; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
318 | const int column = i % 3; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
319 | const int index = i + startingPosition; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
320 | if (index >= tokens.size()) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
321 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
322 | throw BodyParseError{"too few tokens available"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
323 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
324 | bool ok; |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
325 | // note that glm::mat4 is column-major |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
326 | result[column][row] = tokens[index].toFloat(&ok); |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
327 | if (not ok) |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
328 | { |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
329 | throw BodyParseError{"non-numeric values for matrix"}; |
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 | } |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
332 | 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
|
333 | { |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
334 | bool ok; |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
335 | 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
|
336 | result[3][i] = value; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
337 | if (not ok) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
338 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
339 | throw BodyParseError{"non-numeric values for matrix"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
340 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
341 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
342 | return result; |
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 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
345 | static std::unique_ptr<ldraw::Object> parseType0Line( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
346 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
347 | const QStringList& tokens) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
348 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
349 | Q_UNUSED(tokens) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
350 | if (line.startsWith("0 //")) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
351 | { |
141 | 352 | // lol wut |
353 | return std::make_unique<ldraw::Comment>(line.mid(std::strlen("0 //")).trimmed()); | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
354 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
355 | else |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
356 | { |
141 | 357 | return std::make_unique<ldraw::MetaCommand>(line.mid(1).trimmed()); |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
358 | } |
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 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
361 | static std::unique_ptr<ldraw::SubfileReference> parseType1Line( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
362 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
363 | const QStringList& tokens) |
5 | 364 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
365 | Q_UNUSED(line) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
366 | 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
|
367 | 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
|
368 | constexpr int transformPosition = 5; // 5..13 |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
369 | constexpr int namePosition = 14; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
370 | if (tokens.size() != 15) |
5 | 371 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
372 | throw BodyParseError{"wrong amount of tokens in a type-1 line"}; |
5 | 373 | } |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
374 | 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
|
375 | const glm::mat4 transform = matrixFromStrings(tokens, transformPosition, positionPosition); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
376 | 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
|
377 | return std::make_unique<ldraw::SubfileReference>(transform, name, color); |
5 | 378 | } |
379 | ||
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
380 | template<typename T, int NumVertices> |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
381 | static std::unique_ptr<T> parsePolygon( |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
382 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
383 | const QStringList& tokens) |
5 | 384 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
385 | Q_UNUSED(line) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
386 | constexpr int colorPosition = 1; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
387 | auto vertexPosition = [](int n) { return 2 + 3*n; }; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
388 | if (tokens.size() != 2 + 3 * NumVertices) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
389 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
390 | throw BodyParseError{"wrong amount of tokens"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
391 | } |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
392 | 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
|
393 | std::array<glm::vec3, NumVertices> vertices; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
394 | for (int i = 0; i < NumVertices; i += 1) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
395 | { |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
396 | vertices[unsigned_cast(i)] = vertexFromStrings(tokens, vertexPosition(i)); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
397 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
398 | return std::make_unique<T>(vertices, color); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
399 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
400 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
401 | 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
|
402 | { |
141 | 403 | line = line.trimmed(); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
404 | try |
5 | 405 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
406 | const QStringList tokens = line.split(QRegExp{R"(\s+)"}); |
12 | 407 | if (tokens.empty() or tokens == QStringList{{""}}) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
408 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
409 | return std::make_unique<ldraw::Empty>(); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
410 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
411 | bool ok_code; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
412 | const int code = tokens[0].toInt(&ok_code); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
413 | if (not ok_code) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
414 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
415 | throw BodyParseError{"line type was not an integer"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
416 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
417 | switch (code) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
418 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
419 | case 0: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
420 | return parseType0Line(line, tokens); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
421 | case 1: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
422 | return parseType1Line(line, tokens); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
423 | 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
|
424 | return parsePolygon<ldraw::Edge, 2>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
425 | 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
|
426 | return parsePolygon<ldraw::Triangle, 3>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
427 | 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
|
428 | return parsePolygon<ldraw::Quadrilateral, 4>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
429 | 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
|
430 | return parsePolygon<ldraw::ConditionalEdge, 4>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
431 | default: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
432 | throw BodyParseError{utility::format("bad line type '%1'", code)}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
433 | } |
5 | 434 | } |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
435 | catch(const BodyParseError& error) |
5 | 436 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
437 | return std::make_unique<ldraw::ErrorLine>(line, error.message); |
5 | 438 | } |
439 | } |