1 #include "lc_global.h"
2 #include "lc_synth.h"
3 #include "lc_library.h"
4 #include "lc_application.h"
5 #include "lc_file.h"
6 #include "lc_meshloader.h"
7 #include "pieceinf.h"
8 #include <locale.h>
9
10 class lcSynthInfoCurved : public lcSynthInfo
11 {
12 public:
13 lcSynthInfoCurved(float Length, float DefaultScale, int NumSections, bool RigidEdges);
14
15 void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
16 void VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
17
18 protected:
19 float GetSectionTwist(const lcMatrix44& StartTransform, const lcMatrix44& EndTransform) const;
20 void CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const override;
21 static void AddTubeParts(lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections, float Radius, bool IsInner);
22
23 struct lcSynthComponent
24 {
25 lcMatrix44 Transform;
26 float Length;
27 };
28
29 lcSynthComponent mStart;
30 lcSynthComponent mMiddle;
31 lcSynthComponent mEnd;
32 float mCenterLength = 0.0f;
33 int mNumSections;
34 float mDefaultScale;
35 bool mRigidEdges;
36 };
37
38 class lcSynthInfoFlexibleHose : public lcSynthInfoCurved
39 {
40 public:
41 lcSynthInfoFlexibleHose(float Length, int NumSections, const char* EdgePart2);
42
43 protected:
44 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
45
46 const char* mEdgePart2;
47 };
48
49 class lcSynthInfoFlexSystemHose : public lcSynthInfoCurved
50 {
51 public:
52 lcSynthInfoFlexSystemHose(float Length, int NumSections);
53
54 void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
55
56 protected:
57 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
58 };
59
60 class lcSynthInfoPneumaticTube : public lcSynthInfoCurved
61 {
62 public:
63 lcSynthInfoPneumaticTube(float Length, int NumSections, const char* EndPart);
64
65 protected:
66 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
67
68 const char* mEndPart;
69 };
70
71 class lcSynthInfoRibbedHose : public lcSynthInfoCurved
72 {
73 public:
74 lcSynthInfoRibbedHose(float Length, int NumSections);
75
76 protected:
77 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
78 };
79
80 class lcSynthInfoFlexibleAxle : public lcSynthInfoCurved
81 {
82 public:
83 lcSynthInfoFlexibleAxle(float Length, int NumSections);
84
85 protected:
86 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
87 };
88
89 class lcSynthInfoBraidedString : public lcSynthInfoCurved
90 {
91 public:
92 lcSynthInfoBraidedString(float Length, int NumSections);
93
94 protected:
95 void CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const override;
96 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
97 };
98
99 class lcSynthInfoStraight : public lcSynthInfo
100 {
101 public:
102 explicit lcSynthInfoStraight(float Length);
103
104 void VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
105
106 protected:
107 void CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const override;
108 };
109
110 class lcSynthInfoShockAbsorber : public lcSynthInfoStraight
111 {
112 public:
113 explicit lcSynthInfoShockAbsorber(const char* SpringPart);
114
115 void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
116
117 protected:
118 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
119
120 const char* mSpringPart;
121 };
122
123 class lcSynthInfoActuator : public lcSynthInfoStraight
124 {
125 public:
126 explicit lcSynthInfoActuator(const char* BodyPart, const char* PistonPart, const char* AxlePart, float Length, float AxleOffset);
127
128 void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
129
130 protected:
131 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
132
133 const char* mBodyPart;
134 const char* mPistonPart;
135 const char* mAxlePart;
136 float mAxleOffset;
137 };
138
139 class lcSynthInfoUniversalJoint : public lcSynthInfo
140 {
141 public:
142 lcSynthInfoUniversalJoint(float Length, float EndOffset, const char* EndPart, const char* CenterPart);
143
144 void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
145 void VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
146
147 protected:
148 void CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const override;
149 void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
150
151 float mEndOffset;
152 const char* mEndPart;
153 const char* mCenterPart;
154 };
155
lcSynthInit()156 void lcSynthInit()
157 {
158 lcPiecesLibrary* Library = lcGetPiecesLibrary();
159
160 static const struct
161 {
162 char PartID[16];
163 float Length;
164 int NumSections;
165 char EdgePart2[8];
166 }
167 FlexibleHoses[] =
168 {
169 { "73590a.dat", 140.0f, 51, "752.dat" }, // Hose Flexible 8.5L without Tabs
170 { "73590b.dat", 140.0f, 51, "750.dat" }, // Hose Flexible 8.5L with Tabs
171 };
172
173 for (const auto& HoseInfo: FlexibleHoses)
174 {
175 PieceInfo* Info = Library->FindPiece(HoseInfo.PartID, nullptr, false, false);
176
177 if (Info)
178 Info->SetSynthInfo(new lcSynthInfoFlexibleHose(HoseInfo.Length, HoseInfo.NumSections, HoseInfo.EdgePart2));
179 }
180
181 static const struct
182 {
183 char PartID[16];
184 float Length;
185 int NumSections;
186 }
187 FlexSystemHoses[] =
188 {
189 { "76263.dat", 60.0f, 29 }, // Technic Flex-System Hose 3L (60LDU)
190 { "76250.dat", 80.0f, 39 }, // Technic Flex-System Hose 4L (80LDU)
191 { "76307.dat", 100.0f, 49 }, // Technic Flex-System Hose 5L (100LDU)
192 { "76279.dat", 120.0f, 59 }, // Technic Flex-System Hose 6L (120LDU)
193 { "76289.dat", 140.0f, 69 }, // Technic Flex-System Hose 7L (140LDU)
194 { "76260.dat", 160.0f, 79 }, // Technic Flex-System Hose 8L (160LDU)
195 { "76324.dat", 180.0f, 89 }, // Technic Flex-System Hose 9L (180LDU)
196 { "76348.dat", 200.0f, 99 }, // Technic Flex-System Hose 10L (200LDU)
197 { "71505.dat", 220.0f, 109 }, // Technic Flex-System Hose 11L (220LDU)
198 { "71175.dat", 240.0f, 119 }, // Technic Flex-System Hose 12L (240LDU)
199 { "71551.dat", 260.0f, 129 }, // Technic Flex-System Hose 13L (260LDU)
200 { "71177.dat", 280.0f, 139 }, // Technic Flex-System Hose 14L (280LDU)
201 { "71194.dat", 300.0f, 149 }, // Technic Flex-System Hose 15L (300LDU)
202 { "71192.dat", 320.0f, 159 }, // Technic Flex-System Hose 16L (320LDU)
203 { "76270.dat", 340.0f, 169 }, // Technic Flex-System Hose 17L (340LDU)
204 { "71582.dat", 360.0f, 179 }, // Technic Flex-System Hose 18L (360LDU)
205 { "22463.dat", 380.0f, 189 }, // Technic Flex-System Hose 19L (380LDU)
206 { "76276.dat", 400.0f, 199 }, // Technic Flex-System Hose 20L (400LDU)
207 { "70978.dat", 420.0f, 209 }, // Technic Flex-System Hose 21L (420LDU)
208 { "76252.dat", 440.0f, 219 }, // Technic Flex-System Hose 22L (440LDU)
209 { "76254.dat", 460.0f, 229 }, // Technic Flex-System Hose 23L (460LDU)
210 { "76277.dat", 480.0f, 239 }, // Technic Flex-System Hose 24L (480LDU)
211 { "53475.dat", 520.0f, 259 }, // Technic Flex-System Hose 26L (520LDU)
212 { "76280.dat", 560.0f, 279 }, // Technic Flex-System Hose 28L (560LDU)
213 { "76389.dat", 580.0f, 289 }, // Technic Flex-System Hose 29L (580LDU)
214 { "76282.dat", 600.0f, 299 }, // Technic Flex-System Hose 30L (600LDU)
215 { "76283.dat", 620.0f, 309 }, // Technic Flex-System Hose 31L (620LDU)
216 { "57274.dat", 640.0f, 319 }, // Technic Flex-System Hose 32L (640LDU)
217 { "42688.dat", 660.0f, 329 }, // Technic Flex-System Hose 33L (660LDU)
218 { "22461.dat", 680.0f, 339 }, // Technic Flex-System Hose 34L (680LDU)
219 { "46305.dat", 800.0f, 399 }, // Technic Flex-System Hose 40L (800LDU)
220 { "76281.dat", 900.0f, 449 }, // Technic Flex-System Hose 45L (900LDU)
221 { "22296.dat", 1060.0f, 529 }, // Technic Flex-System Hose 53L (1060LDU)
222 };
223
224 for (const auto& HoseInfo: FlexSystemHoses)
225 {
226 PieceInfo* Info = Library->FindPiece(HoseInfo.PartID, nullptr, false, false);
227
228 if (Info)
229 Info->SetSynthInfo(new lcSynthInfoFlexSystemHose(HoseInfo.Length, HoseInfo.NumSections));
230 }
231
232 static const struct
233 {
234 char PartID[16];
235 float Length;
236 int NumSections;
237 }
238 PneumaticTubes[] =
239 {
240 { "21761-f1.dat", 60.0f, 10 }, // Technic Pneumatic Tube 3L
241 { "26445-f1.dat", 80.0f, 20 }, // Technic Pneumatic Tube 4L
242 { "14653-f1.dat", 100.0f, 20 }, // Technic Pneumatic Tube 5L
243 { "21766-f1.dat", 120.0f, 40 }, // Technic Pneumatic Tube 6L
244 { "14657-f1.dat", 140.0f, 40 }, // Technic Pneumatic Tube 7L
245 { "21837-f1.dat", 160.0f, 40 }, // Technic Pneumatic Tube 8L
246 { "21826-f1.dat", 180.0f, 40 }, // Technic Pneumatic Tube 9L
247 { "21767-f1.dat", 200.0f, 80 }, // Technic Pneumatic Tube 10L
248 { "63539-f1.dat", 240.0f, 80 }, // Technic Pneumatic Tube 12L
249 { "37467-f1.dat", 260.0f, 80 }, // Technic Pneumatic Tube 13L
250 { "37461-f1.dat", 280.0f, 80 }, // Technic Pneumatic Tube 14L
251 { "87948-f1.dat", 320.0f, 80 }, // Technic Pneumatic Tube 16L
252 { "53168-f1.dat", 340.0f, 80 }, // Technic Pneumatic Tube 17L
253 { "21839-f1.dat", 380.0f, 160 }, // Technic Pneumatic Tube 19L
254 { "87950-f1.dat", 400.0f, 160 }, // Technic Pneumatic Tube 20L
255 { "53184-f1.dat", 420.0f, 160 }, // Technic Pneumatic Tube 21L
256 { "26436-f1.dat", 460.0f, 160 }, // Technic Pneumatic Tube 23L
257 { "21830-f1.dat", 540.0f, 160 }, // Technic Pneumatic Tube 27L
258 { "21825-f1.dat", 560.0f, 160 }, // Technic Pneumatic Tube 28L
259 { "21833-f1.dat", 600.0f, 160 }, // Technic Pneumatic Tube 30L
260 { "26440-f1.dat", 640.0f, 160 }, // Technic Pneumatic Tube 32L
261 { "96889-f1.dat", 660.0f, 160 }, // Technic Pneumatic Tube 33L
262 { "87949-f1.dat", 720.0f, 320 }, // Technic Pneumatic Tube 36L
263 { "21835-f1.dat", 740.0f, 320 }, // Technic Pneumatic Tube 37L
264 { "14661-f1.dat", 780.0f, 320 }, // Technic Pneumatic Tube 39L
265 { "26438-f1.dat", 800.0f, 320 }, // Technic Pneumatic Tube 40L
266 { "44079-f1.dat", 840.0f, 320 }, // Technic Pneumatic Tube 42L
267 { "26439-f1.dat", 960.0f, 320 }, // Technic Pneumatic Tube 48L
268 { "96890-f1.dat", 1080.0f, 320 }, // Technic Pneumatic Tube 54L
269 { "96891-f1.dat", 1600.0f, 320 }, // Technic Pneumatic Tube 80L
270 };
271
272 for (const auto& TubeInfo: PneumaticTubes)
273 {
274 PieceInfo* Info = Library->FindPiece(TubeInfo.PartID, nullptr, false, false);
275
276 if (Info)
277 Info->SetSynthInfo(new lcSynthInfoPneumaticTube(TubeInfo.Length, TubeInfo.NumSections, "71533k02.dat"));
278
279 auto RegularInfo = TubeInfo;
280 RegularInfo.PartID[7] = '2';
281 RegularInfo.Length -= 40.0f;
282
283 Info = Library->FindPiece(RegularInfo.PartID, nullptr, false, false);
284
285 if (Info)
286 Info->SetSynthInfo(new lcSynthInfoPneumaticTube(RegularInfo.Length, RegularInfo.NumSections, "71533k01.dat"));
287 }
288
289 static const struct
290 {
291 char PartID[16];
292 float Length;
293 int NumSections;
294 }
295 RibbedHoses[] =
296 {
297 { "72504.dat", 31.25f, 4 }, // Technic Ribbed Hose 2L
298 { "72706.dat", 50.00f, 7 }, // Technic Ribbed Hose 3L
299 { "71952.dat", 75.00f, 11 }, // Technic Ribbed Hose 4L
300 { "72853.dat", 93.75f, 14 }, // Technic Ribbed Hose 5L
301 { "71944.dat", 112.50f, 17 }, // Technic Ribbed Hose 6L
302 { "57719.dat", 131.25f, 20 }, // Technic Ribbed Hose 7L
303 { "71951.dat", 150.00f, 23 }, // Technic Ribbed Hose 8L
304 { "71917.dat", 175.00f, 27 }, // Technic Ribbed Hose 9L
305 { "71949.dat", 193.75f, 30 }, // Technic Ribbed Hose 10L
306 { "71986.dat", 212.50f, 33 }, // Technic Ribbed Hose 11L
307 { "71819.dat", 231.25f, 36 }, // Technic Ribbed Hose 12L
308 { "71923.dat", 275.00f, 43 }, // Technic Ribbed Hose 14L
309 { "71946.dat", 293.75f, 46 }, // Technic Ribbed Hose 15L
310 { "71947.dat", 312.50f, 49 }, // Technic Ribbed Hose 16L
311 { "22900.dat", 331.25f, 52 }, // Technic Ribbed Hose 17L
312 { "72039.dat", 350.00f, 55 }, // Technic Ribbed Hose 18L
313 { "43675.dat", 375.00f, 58 }, // Technic Ribbed Hose 19L
314 { "23397.dat", 468.75f, 74 }, // Technic Ribbed Hose 24L
315 { "33763.dat", 512.50f, 81 }, // Technic Ribbed Hose 26L
316 };
317
318 for (const auto& HoseInfo: RibbedHoses)
319 {
320 PieceInfo* Info = Library->FindPiece(HoseInfo.PartID, nullptr, false, false);
321
322 if (Info)
323 Info->SetSynthInfo(new lcSynthInfoRibbedHose(HoseInfo.Length, HoseInfo.NumSections));
324 }
325
326 static const struct
327 {
328 char PartID[16];
329 float Length;
330 int NumSections;
331 }
332 FlexibleAxles[] =
333 {
334 { "32580.dat", 120.00f, 15 }, // Technic Axle Flexible 7
335 { "32199.dat", 200.00f, 35 }, // Technic Axle Flexible 11
336 { "55709.dat", 200.00f, 35 }, // Technic Axle Flexible 11
337 { "32200.dat", 220.00f, 40 }, // Technic Axle Flexible 12
338 { "32201.dat", 260.00f, 50 }, // Technic Axle Flexible 14
339 { "32202.dat", 300.00f, 60 }, // Technic Axle Flexible 16
340 { "32235.dat", 360.00f, 75 }, // Technic Axle Flexible 19
341 };
342
343 for (const auto& AxleInfo: FlexibleAxles)
344 {
345 PieceInfo* Info = Library->FindPiece(AxleInfo.PartID, nullptr, false, false);
346
347 if (Info)
348 Info->SetSynthInfo(new lcSynthInfoFlexibleAxle(AxleInfo.Length, AxleInfo.NumSections));
349 }
350
351 static const struct
352 {
353 char PartID[16];
354 float Length;
355 int NumSections;
356 }
357 BraidedStrings[] =
358 {
359 { "76384.dat", 200.00f, 46 }, // String Braided 11L with End Studs
360 { "75924.dat", 400.00f, 96 }, // String Braided 21L with End Studs
361 { "572C02.dat", 800.00f, 196 }, // String Braided 41L with End Studs
362 };
363
364 for (const auto& StringInfo: BraidedStrings)
365 {
366 PieceInfo* Info = Library->FindPiece(StringInfo.PartID, nullptr, false, false);
367
368 if (Info)
369 Info->SetSynthInfo(new lcSynthInfoBraidedString(StringInfo.Length, StringInfo.NumSections));
370 }
371
372 static const struct
373 {
374 char PartID[16];
375 char SpringPart[16];
376 }
377 ShockAbsorbers[] =
378 {
379 { "73129.dat", "70038.dat" }, // Technic Shock Absorber 6.5L
380 { "41838.dat", "41837.dat" }, // Technic Shock Absorber 6.5L Soft
381 { "76138.dat", "71953.dat" }, // Technic Shock Absorber 6.5L Stiff
382 { "76537.dat", "22977.dat" }, // Technic Shock Absorber 6.5L Extra Stiff
383 };
384
385 for (const auto& AbsorberInfo: ShockAbsorbers)
386 {
387 PieceInfo* Info = Library->FindPiece(AbsorberInfo.PartID, nullptr, false, false);
388
389 if (Info)
390 Info->SetSynthInfo(new lcSynthInfoShockAbsorber(AbsorberInfo.SpringPart));
391 }
392
393 static const struct
394 {
395 char PartID[16];
396 char BodyPart[16];
397 char PistonPart[16];
398 char AxlePart[16];
399 float Length;
400 float AxleOffset;
401 }
402 Actuators[] =
403 {
404 { "61927-F1.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 170.00f, 0.0f }, // Technic Linear Actuator 8 x 2 x 2 (Contracted)
405 { "61927-F2.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 270.00f, 0.0f }, // Technic Linear Actuator 8 x 2 x 2 (Extended)
406 { "61927C01.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 270.00f, 0.0f }, // Moved to 61927-f2 (was Technic Power Functions Linear Actuator (Extended))
407 { "61927.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 170.00f, 0.0f }, // Moved to 61927-f1 (was Technic Power Functions Linear Actuator (Contracted))
408 { "92693C01-F1.dat", "92693c01.dat", "92696.dat", "92695.dat", 120.00f, 30.0f }, // Technic Linear Actuator 4 x 1 x 1 (Contracted)
409 { "92693C01-F2.dat", "92693c01.dat", "92696.dat", "92695.dat", 180.00f, 30.0f }, // Technic Linear Actuator 4 x 1 x 1 (Extended)
410 { "92693C02.dat", "92693c01.dat", "92696.dat", "92695.dat", 120.00f, 30.0f }, // Moved to 92693c01-f1 (was Technic Linear Actuator Small (Contracted))
411 { "92693C03.dat", "92693c01.dat", "92696.dat", "92695.dat", 180.00f, 30.0f }, // Moved to 92693c01-f2 (was Technic Linear Actuator Small (Extended))
412 };
413
414 for (const auto& ActuatorInfo: Actuators)
415 {
416 PieceInfo* Info = Library->FindPiece(ActuatorInfo.PartID, nullptr, false, false);
417
418 if (Info)
419 Info->SetSynthInfo(new lcSynthInfoActuator(ActuatorInfo.BodyPart, ActuatorInfo.PistonPart,
420 ActuatorInfo.AxlePart, ActuatorInfo.Length, ActuatorInfo.AxleOffset));
421 }
422
423 static const struct
424 {
425 char PartID[16];
426 float Length;
427 float EndOffset;
428 char EndPart[16];
429 char CenterPart[16];
430 }
431 UniversalJoints[] =
432 {
433 { "61903.dat", 60.00f, 0.0f, "62520.dat", "62519.dat" }, // Technic Universal Joint 3L (Complete)
434 { "3712C01.dat", 60.00f, 30.0f, "3712.dat", "3326.dat" }, // Technic Universal Joint 4L with Bush Ends with Centre Type 2 (Complete)
435 { "3712C03.dat", 60.00f, 30.0f, "3712.dat", "3326a.dat" }, // Technic Universal Joint 4L with Bush Ends with Centre Type 1 (Complete)
436 { "575C01.dat", 60.00f, 30.0f, "575.dat", "3326a.dat" } // Technic Universal Joint Type 1 (Complete)
437 };
438
439 for (const auto& JointInfo: UniversalJoints)
440 {
441 PieceInfo* Info = Library->FindPiece(JointInfo.PartID, nullptr, false, false);
442
443 if (Info)
444 Info->SetSynthInfo(new lcSynthInfoUniversalJoint(JointInfo.Length, JointInfo.EndOffset, JointInfo.EndPart, JointInfo.CenterPart));
445 }
446
447 // "758C01" // Hose Flexible 12L
448 }
449
lcSynthInfo(float Length)450 lcSynthInfo::lcSynthInfo(float Length)
451 : mLength(Length)
452 {
453 }
454
lcSynthInfoCurved(float Length,float DefaultScale,int NumSections,bool RigidEdges)455 lcSynthInfoCurved::lcSynthInfoCurved(float Length, float DefaultScale, int NumSections, bool RigidEdges)
456 : lcSynthInfo(Length), mNumSections(NumSections), mDefaultScale(DefaultScale), mRigidEdges(RigidEdges)
457 {
458 mCurve = true;
459
460 mStart.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
461 mEnd.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
462 }
463
lcSynthInfoFlexibleHose(float Length,int NumSections,const char * EdgePart2)464 lcSynthInfoFlexibleHose::lcSynthInfoFlexibleHose(float Length, int NumSections, const char* EdgePart2)
465 : lcSynthInfoCurved(Length, 12.f, NumSections, true),
466 mEdgePart2(EdgePart2)
467 {
468 mStart.Length = 5.0f;
469 mMiddle.Length = 2.56f;
470 mEnd.Length = 5.0f;
471 mCenterLength = 4.56f;
472 }
473
lcSynthInfoFlexSystemHose(float Length,int NumSections)474 lcSynthInfoFlexSystemHose::lcSynthInfoFlexSystemHose(float Length, int NumSections)
475 : lcSynthInfoCurved(Length, 12.f, NumSections, true)
476 {
477 mStart.Transform = lcMatrix44Identity();
478 mEnd.Transform = lcMatrix44Identity();
479 mStart.Length = 1.0f;
480 mMiddle.Length = 2.0f;
481 mEnd.Length = 1.0f;
482 }
483
lcSynthInfoPneumaticTube(float Length,int NumSections,const char * EndPart)484 lcSynthInfoPneumaticTube::lcSynthInfoPneumaticTube(float Length, int NumSections, const char* EndPart)
485 : lcSynthInfoCurved(Length, 12.f, NumSections, true),
486 mEndPart(EndPart)
487 {
488 mStart.Length = 0.0f;
489 mMiddle.Length = mLength / NumSections;
490 mEnd.Length = 0.0f;
491 }
492
lcSynthInfoRibbedHose(float Length,int NumSections)493 lcSynthInfoRibbedHose::lcSynthInfoRibbedHose(float Length, int NumSections)
494 : lcSynthInfoCurved(Length, 80.0f, NumSections, false)
495 {
496 mStart.Length = 6.25f;
497 mMiddle.Length = 6.25f;
498 mEnd.Length = 6.25f;
499 }
500
lcSynthInfoFlexibleAxle(float Length,int NumSections)501 lcSynthInfoFlexibleAxle::lcSynthInfoFlexibleAxle(float Length, int NumSections)
502 : lcSynthInfoCurved(Length, 12.0f, NumSections, true)
503 {
504 mStart.Length = 30.0f;
505 mMiddle.Length = 4.0f;
506 mEnd.Length = 30.0f;
507 }
508
lcSynthInfoBraidedString(float Length,int NumSections)509 lcSynthInfoBraidedString::lcSynthInfoBraidedString(float Length, int NumSections)
510 : lcSynthInfoCurved(Length, 12.0f, NumSections, true)
511 {
512 mStart.Transform = lcMatrix44Identity();
513 mEnd.Transform = lcMatrix44Identity();
514 mStart.Length = 8.0f;
515 mMiddle.Length = 4.0f;
516 mEnd.Length = 8.0f;
517 }
518
lcSynthInfoStraight(float Length)519 lcSynthInfoStraight::lcSynthInfoStraight(float Length)
520 : lcSynthInfo(Length)
521 {
522 mUnidirectional = true;
523 }
524
lcSynthInfoShockAbsorber(const char * SpringPart)525 lcSynthInfoShockAbsorber::lcSynthInfoShockAbsorber(const char* SpringPart)
526 : lcSynthInfoStraight(110.00f), mSpringPart(SpringPart)
527 {
528 }
529
lcSynthInfoActuator(const char * BodyPart,const char * PistonPart,const char * AxlePart,float Length,float AxleOffset)530 lcSynthInfoActuator::lcSynthInfoActuator(const char* BodyPart, const char* PistonPart, const char* AxlePart, float Length, float AxleOffset)
531 : lcSynthInfoStraight(Length), mBodyPart(BodyPart), mPistonPart(PistonPart), mAxlePart(AxlePart), mAxleOffset(AxleOffset)
532 {
533 }
534
lcSynthInfoUniversalJoint(float Length,float EndOffset,const char * EndPart,const char * CenterPart)535 lcSynthInfoUniversalJoint::lcSynthInfoUniversalJoint(float Length, float EndOffset, const char* EndPart, const char* CenterPart)
536 : lcSynthInfo(Length), mEndOffset(EndOffset), mEndPart(EndPart), mCenterPart(CenterPart)
537 {
538 mNondirectional = true;
539 }
540
GetDefaultControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const541 void lcSynthInfoCurved::GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
542 {
543 ControlPoints.SetSize(2);
544
545 float HalfLength = mLength / 2.0f;
546 float Scale = lcMin(mDefaultScale, HalfLength);
547
548 ControlPoints[0].Transform = lcMatrix44Translation(lcVector3(-HalfLength, 0.0f, 0.0f));
549 ControlPoints[1].Transform = lcMatrix44Translation(lcVector3( HalfLength, 0.0f, 0.0f));
550
551 ControlPoints[0].Scale = Scale;
552 ControlPoints[1].Scale = Scale;
553 }
554
VerifyControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const555 void lcSynthInfoCurved::VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
556 {
557 if (ControlPoints.GetSize() < 2)
558 GetDefaultControlPoints(ControlPoints);
559 }
560
GetDefaultControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const561 void lcSynthInfoFlexSystemHose::GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
562 {
563 lcSynthInfoCurved::GetDefaultControlPoints(ControlPoints);
564
565 ControlPoints[0].Transform = lcMatrix44Translation(lcVector3(0.0f, 0.0f, -mLength));
566 ControlPoints[1].Transform = lcMatrix44Translation(lcVector3(0.0f, 0.0f, 0.0f));
567 }
568
VerifyControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const569 void lcSynthInfoStraight::VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
570 {
571 if (ControlPoints.GetSize() < 2)
572 GetDefaultControlPoints(ControlPoints);
573 else
574 ControlPoints.SetSize(2);
575 }
576
GetDefaultControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const577 void lcSynthInfoShockAbsorber::GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
578 {
579 ControlPoints.SetSize(2);
580
581 ControlPoints[0].Transform = lcMatrix44Translation(lcVector3(0.0f, 0.0f, -mLength));
582 ControlPoints[1].Transform = lcMatrix44Translation(lcVector3(0.0f, 0.0f, 0.0f));
583
584 ControlPoints[0].Scale = 1.0f;
585 ControlPoints[1].Scale = 1.0f;
586 }
587
GetDefaultControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const588 void lcSynthInfoActuator::GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
589 {
590 ControlPoints.SetSize(2);
591
592 ControlPoints[0].Transform = lcMatrix44(lcMatrix33(lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
593 ControlPoints[1].Transform = lcMatrix44(lcMatrix33(lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, mLength, 0.0f));
594
595 ControlPoints[0].Scale = 1.0f;
596 ControlPoints[1].Scale = 1.0f;
597 }
598
GetDefaultControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const599 void lcSynthInfoUniversalJoint::GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
600 {
601 ControlPoints.SetSize(1);
602 float HalfLength = mLength / 2;
603
604 ControlPoints[0].Transform = lcMatrix44Translation(lcVector3(0.0f, HalfLength, 0.0f));
605 ControlPoints[0].Scale = 1.0f;
606 }
607
VerifyControlPoints(lcArray<lcPieceControlPoint> & ControlPoints) const608 void lcSynthInfoUniversalJoint::VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
609 {
610 if (ControlPoints.IsEmpty())
611 GetDefaultControlPoints(ControlPoints);
612 else
613 ControlPoints.SetSize(1);
614 }
615
GetSectionTwist(const lcMatrix44 & StartTransform,const lcMatrix44 & EndTransform) const616 float lcSynthInfoCurved::GetSectionTwist(const lcMatrix44& StartTransform, const lcMatrix44& EndTransform) const
617 {
618 lcVector3 StartTangent(StartTransform[1].x, StartTransform[1].y, StartTransform[1].z);
619 lcVector3 EndTangent(EndTransform[1].x, EndTransform[1].y, EndTransform[1].z);
620 lcVector3 StartUp(StartTransform[2].x, StartTransform[2].y, StartTransform[2].z);
621 lcVector3 EndUp(EndTransform[2].x, EndTransform[2].y, EndTransform[2].z);
622
623 float TangentDot = lcDot(StartTangent, EndTangent);
624 float UpDot = lcDot(StartUp, EndUp);
625
626 if (TangentDot > 0.99f && UpDot > 0.99f)
627 return 0.0f;
628
629 if (fabs(TangentDot) > 0.99f)
630 {
631 return acosf(lcClamp(lcDot(EndUp, StartUp), -1.0f, 1.0f));
632 }
633 else if (TangentDot > -0.99f)
634 {
635 lcVector3 Axis = lcCross(StartTangent, EndTangent);
636 float Angle = acosf(lcClamp(TangentDot, -1.0f, 1.0f));
637
638 lcMatrix33 Rotation = lcMatrix33FromAxisAngle(Axis, Angle);
639 lcVector3 AdjustedStartUp = lcMul(StartUp, Rotation);
640 return acosf(lcClamp(lcDot(EndUp, AdjustedStartUp), -1.0f, 1.0f));
641 }
642
643 lcVector3 StartSide(StartTransform[0].x, StartTransform[0].y, StartTransform[0].z);
644 lcVector3 EndSide(EndTransform[0].x, EndTransform[0].y, EndTransform[0].z);
645
646 float SideDot = lcDot(StartSide, EndSide);
647
648 if (fabs(SideDot) < 0.99f)
649 {
650 lcVector3 Axis = lcCross(StartSide, EndSide);
651 float Angle = acosf(SideDot);
652
653 lcMatrix33 Rotation = lcMatrix33FromAxisAngle(Axis, Angle);
654 lcVector3 AdjustedStartUp = lcMul(StartUp, Rotation);
655 return acosf(lcClamp(lcDot(EndUp, AdjustedStartUp), -1.0f, 1.0f));
656 }
657
658 return 0.0f;
659 }
660
CalculateSections(const lcArray<lcPieceControlPoint> & ControlPoints,lcArray<lcMatrix44> & Sections,SectionCallbackFunc SectionCallback) const661 void lcSynthInfoCurved::CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const
662 {
663 float SectionLength = 0.0f;
664
665 for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize() - 1 && Sections.GetSize() < mNumSections + 2; ControlPointIdx++)
666 {
667 lcVector3 SegmentControlPoints[4];
668
669 lcMatrix44 StartTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx].Transform);
670 lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx + 1].Transform);
671 StartTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mStart.Transform), lcMatrix33(StartTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), StartTransform.GetTranslation());
672
673 if (ControlPointIdx == 0)
674 {
675 if (mRigidEdges)
676 {
677 StartTransform.SetTranslation(lcMul30(lcVector3(0.0f, mStart.Length, 0.0f), StartTransform) + StartTransform.GetTranslation());
678 SectionLength = 0.0f;
679 }
680 else
681 SectionLength = mStart.Length;
682
683 Sections.Add(StartTransform);
684 }
685
686 EndTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mEnd.Transform), lcMatrix33(EndTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
687
688 SegmentControlPoints[0] = StartTransform.GetTranslation();
689 SegmentControlPoints[1] = lcMul31(lcVector3(0.0f, ControlPoints[ControlPointIdx].Scale, 0.0f), StartTransform);
690 SegmentControlPoints[2] = lcMul31(lcVector3(0.0f, -ControlPoints[ControlPointIdx + 1].Scale, 0.0f), EndTransform);
691 SegmentControlPoints[3] = EndTransform.GetTranslation();
692
693 const int NumCurvePoints = 8192;
694 lcArray<lcVector3> CurvePoints;
695 CurvePoints.AllocGrow(NumCurvePoints);
696
697 for (int PointIdx = 0; PointIdx < NumCurvePoints; PointIdx++)
698 {
699 float t = (float)PointIdx / (float)(NumCurvePoints - 1);
700 float it = 1.0f - t;
701
702 lcVector3 Position = it * it * it * SegmentControlPoints[0] + it * it * 3.0f * t * SegmentControlPoints[1] + it * 3.0 * t * t * SegmentControlPoints[2] + t * t * t * SegmentControlPoints[3];
703 CurvePoints.Add(Position);
704 }
705
706 float CurrentSegmentLength = 0.0f;
707 float TotalSegmentLength = 0.0f;
708
709 for (int PointIdx = 0; PointIdx < CurvePoints.GetSize() - 1; PointIdx++)
710 TotalSegmentLength += lcLength(CurvePoints[PointIdx] - CurvePoints[PointIdx + 1]);
711
712 lcVector3 StartUp = lcMul30(lcVector3(1.0f, 0.0f, 0.0f), StartTransform);
713 float Twist = GetSectionTwist(StartTransform, EndTransform);
714 int CurrentPointIndex = 0;
715
716 while (CurrentPointIndex < CurvePoints.GetSize() - 1)
717 {
718 float Length = lcLength(CurvePoints[CurrentPointIndex + 1] - CurvePoints[CurrentPointIndex]);
719 CurrentSegmentLength += Length;
720 SectionLength -= Length;
721 CurrentPointIndex++;
722
723 if (SectionLength > 0.0f)
724 continue;
725
726 float t = (float)CurrentPointIndex / (float)(NumCurvePoints - 1);
727 float it = 1.0f - t;
728
729 lcVector3 Tangent = lcNormalize(-3.0f * it * it * SegmentControlPoints[0] + (3.0f * it * it - 6.0f * t * it) * SegmentControlPoints[1] + (-3.0f * t * t + 6.0f * t * it) * SegmentControlPoints[2] + 3.0f * t * t * SegmentControlPoints[3]);
730 lcVector3 Up;
731
732 if (Twist)
733 {
734 Up = lcMul(StartUp, lcMatrix33FromAxisAngle(Tangent, Twist * (CurrentSegmentLength / TotalSegmentLength)));
735 CurrentSegmentLength = 0.0f;
736 }
737 else
738 Up = StartUp;
739
740 lcVector3 Side = lcNormalize(lcCross(Tangent, Up));
741 Up = lcNormalize(lcCross(Side, Tangent));
742 StartUp = Up;
743
744 Sections.Add(lcMatrix44(lcMatrix33(Up, Tangent, Side), CurvePoints[CurrentPointIndex]));
745
746 if (SectionCallback)
747 SectionCallback(CurvePoints[CurrentPointIndex], ControlPointIdx, t);
748
749 if (Sections.GetSize() == mNumSections + 2)
750 break;
751
752 if (mCenterLength != 0.0f && (Sections.GetSize() == mNumSections / 2 + 1))
753 SectionLength += mCenterLength;
754 else
755 SectionLength += mMiddle.Length;
756
757 if (Sections.GetSize() == mNumSections + 1 && !mRigidEdges)
758 SectionLength += mEnd.Length;
759 }
760 }
761
762 while (Sections.GetSize() < mNumSections + 2)
763 {
764 lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPoints.GetSize() - 1].Transform);
765 EndTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mEnd.Transform), lcMatrix33(EndTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
766 lcVector3 Position = lcMul31(lcVector3(0.0f, SectionLength, 0.0f), EndTransform);
767 EndTransform.SetTranslation(Position);
768 Sections.Add(EndTransform);
769
770 if (SectionCallback)
771 SectionCallback(Position, ControlPoints.GetSize() - 1, 1.0f);
772
773 if (mCenterLength != 0.0f && (Sections.GetSize() == mNumSections / 2 + 1))
774 SectionLength += mCenterLength;
775 else
776 SectionLength += mMiddle.Length;
777
778 if (Sections.GetSize() == mNumSections + 1 && !mRigidEdges)
779 SectionLength += mEnd.Length;
780 }
781 }
782
CalculateSections(const lcArray<lcPieceControlPoint> & ControlPoints,lcArray<lcMatrix44> & Sections,SectionCallbackFunc SectionCallback) const783 void lcSynthInfoBraidedString::CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const
784 {
785 float SectionLength = 0.0f;
786
787 for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize() - 1 && Sections.GetSize() < mNumSections + 2; ControlPointIdx++)
788 {
789 lcVector3 SegmentControlPoints[4];
790
791 lcMatrix44 StartTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx].Transform);
792 lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx + 1].Transform);
793 StartTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mStart.Transform), lcMatrix33(StartTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), StartTransform.GetTranslation());
794
795 if (ControlPointIdx == 0)
796 {
797 if (mRigidEdges)
798 {
799 StartTransform.SetTranslation(lcMul30(lcVector3(mStart.Length, 0.0f, 0.0f), StartTransform) + StartTransform.GetTranslation());
800 SectionLength = 0.0f;
801 }
802 else
803 SectionLength = mStart.Length;
804
805 Sections.Add(StartTransform);
806 }
807
808 EndTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mEnd.Transform), lcMatrix33(EndTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
809
810 SegmentControlPoints[0] = StartTransform.GetTranslation();
811 SegmentControlPoints[1] = lcMul31(lcVector3(ControlPoints[ControlPointIdx].Scale, 0.0f, 0.0f), StartTransform);
812 SegmentControlPoints[2] = lcMul31(lcVector3(-ControlPoints[ControlPointIdx + 1].Scale, 0.0f, 0.0f), EndTransform);
813 SegmentControlPoints[3] = EndTransform.GetTranslation();
814
815 const int NumCurvePoints = 8192;
816 lcArray<lcVector3> CurvePoints;
817 CurvePoints.AllocGrow(NumCurvePoints);
818
819 for (int PointIdx = 0; PointIdx < NumCurvePoints; PointIdx++)
820 {
821 float t = (float)PointIdx / (float)(NumCurvePoints - 1);
822 float it = 1.0f - t;
823
824 lcVector3 Position = it * it * it * SegmentControlPoints[0] + it * it * 3.0f * t * SegmentControlPoints[1] + it * 3.0 * t * t * SegmentControlPoints[2] + t * t * t * SegmentControlPoints[3];
825 CurvePoints.Add(Position);
826 }
827
828 float CurrentSegmentLength = 0.0f;
829 float TotalSegmentLength = 0.0f;
830
831 for (int PointIdx = 0; PointIdx < CurvePoints.GetSize() - 1; PointIdx++)
832 TotalSegmentLength += lcLength(CurvePoints[PointIdx] - CurvePoints[PointIdx + 1]);
833
834 lcVector3 StartUp = lcMul30(lcVector3(0.0f, 1.0f, 0.0f), StartTransform);
835 float Twist = GetSectionTwist(StartTransform, EndTransform);
836 int CurrentPointIndex = 0;
837
838 while (CurrentPointIndex < CurvePoints.GetSize() - 1)
839 {
840 float Length = lcLength(CurvePoints[CurrentPointIndex + 1] - CurvePoints[CurrentPointIndex]);
841 CurrentSegmentLength += Length;
842 SectionLength -= Length;
843 CurrentPointIndex++;
844
845 if (SectionLength > 0.0f)
846 continue;
847
848 float t = (float)CurrentPointIndex / (float)(NumCurvePoints - 1);
849 float it = 1.0f - t;
850
851 lcVector3 Tangent = lcNormalize(-3.0f * it * it * SegmentControlPoints[0] + (3.0f * it * it - 6.0f * t * it) * SegmentControlPoints[1] + (-3.0f * t * t + 6.0f * t * it) * SegmentControlPoints[2] + 3.0f * t * t * SegmentControlPoints[3]);
852 lcVector3 Up;
853
854 if (Twist)
855 {
856 Up = lcMul(StartUp, lcMatrix33FromAxisAngle(Tangent, Twist * (CurrentSegmentLength / TotalSegmentLength)));
857 CurrentSegmentLength = 0.0f;
858 }
859 else
860 Up = StartUp;
861
862 lcVector3 Side = lcNormalize(lcCross(Tangent, Up));
863 Up = lcNormalize(lcCross(Side, Tangent));
864 StartUp = Up;
865
866 Sections.Add(lcMatrix44(lcMatrix33(Tangent, Up, -Side), CurvePoints[CurrentPointIndex]));
867
868 if (SectionCallback)
869 SectionCallback(CurvePoints[CurrentPointIndex], ControlPointIdx, t);
870
871 if (Sections.GetSize() == mNumSections + 2)
872 break;
873
874 if (mCenterLength != 0.0f && (Sections.GetSize() == mNumSections / 2 + 1))
875 SectionLength += mCenterLength;
876 else
877 SectionLength += mMiddle.Length;
878
879 if (Sections.GetSize() == mNumSections + 1 && !mRigidEdges)
880 SectionLength += mEnd.Length;
881 }
882 }
883
884 while (Sections.GetSize() < mNumSections + 2)
885 {
886 lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPoints.GetSize() - 1].Transform);
887 EndTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mEnd.Transform), lcMatrix33(EndTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
888 lcVector3 Position = lcMul31(lcVector3(SectionLength, 0.0f, 0.0f), EndTransform);
889 EndTransform.SetTranslation(Position);
890 Sections.Add(EndTransform);
891
892 if (SectionCallback)
893 SectionCallback(Position, ControlPoints.GetSize() - 1, 1.0f);
894
895 if (mCenterLength != 0.0f && (Sections.GetSize() == mNumSections / 2 + 1))
896 SectionLength += mCenterLength;
897 else
898 SectionLength += mMiddle.Length;
899
900 if (Sections.GetSize() == mNumSections + 1 && !mRigidEdges)
901 SectionLength += mEnd.Length;
902 }
903 }
904
CalculateSections(const lcArray<lcPieceControlPoint> & ControlPoints,lcArray<lcMatrix44> & Sections,SectionCallbackFunc SectionCallback) const905 void lcSynthInfoStraight::CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const
906 {
907 for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize(); ControlPointIdx++)
908 {
909 lcMatrix44 Transform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx].Transform);
910 Sections.Add(Transform);
911
912 if (SectionCallback)
913 SectionCallback(Transform.GetTranslation(), ControlPointIdx, 1.0f);
914 }
915 }
916
CalculateSections(const lcArray<lcPieceControlPoint> & ControlPoints,lcArray<lcMatrix44> & Sections,SectionCallbackFunc SectionCallback) const917 void lcSynthInfoUniversalJoint::CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const
918 {
919 for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize(); ControlPointIdx++)
920 {
921 lcMatrix44 Transform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx].Transform);
922 Sections.Add(Transform);
923
924 if (SectionCallback)
925 SectionCallback(Transform.GetTranslation(), ControlPointIdx, 1.0f);
926 }
927 }
928
AddParts(lcMemFile & File,lcLibraryMeshData &,const lcArray<lcMatrix44> & Sections) const929 void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcArray<lcMatrix44>& Sections) const
930 {
931 char Line[256];
932 const int NumEdgeParts = 2;
933
934 const lcMatrix33 EdgeTransforms[2] =
935 {
936 lcMatrix33(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, -1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f)),
937 lcMatrix33(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f))
938 };
939
940 const char* EdgeParts[2] =
941 {
942 "755.dat", mEdgePart2
943 };
944
945 for (int PartIdx = 0; PartIdx < NumEdgeParts; PartIdx++)
946 {
947 const int SectionIdx = 0;
948 lcMatrix33 Transform(lcMul(lcMul(EdgeTransforms[PartIdx], lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIdx])));
949 lcVector3 Offset = lcMul31(lcVector3(0.0f, -5.0f, 0.0f), Sections[SectionIdx]);
950
951 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
952 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
953
954 File.WriteBuffer(Line, strlen(Line));
955 }
956
957 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
958 {
959 lcMatrix33 Transform = lcMatrix33(Sections[SectionIdx]);
960 lcVector3 Offset = Sections[SectionIdx].GetTranslation();
961
962 if (SectionIdx < Sections.GetSize() / 2)
963 Transform = lcMul(lcMatrix33(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, -1.0f, 0.0f), lcVector3(-1.0f, 0.0f, 0.0f)), Transform);
964 else if (SectionIdx != Sections.GetSize() / 2)
965 Transform = lcMul(lcMatrix33(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, 1.0f, 0.0f), lcVector3( 1.0f, 0.0f, 0.0f)), Transform);
966 else
967 Transform = lcMul(lcMatrix33(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, 1.0f, 0.0f), lcVector3( 1.0f, 0.0f, 0.0f)), Transform);
968
969 const char* Part = SectionIdx != Sections.GetSize() / 2 ? "754.dat" : "756.dat";
970
971 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
972 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], Part);
973
974 File.WriteBuffer(Line, strlen(Line));
975 }
976
977 for (int PartIdx = 0; PartIdx < NumEdgeParts; PartIdx++)
978 {
979 const int SectionIdx = Sections.GetSize() - 1;
980 lcMatrix33 Transform(lcMul(EdgeTransforms[PartIdx], lcMatrix33(Sections[SectionIdx])));
981 lcVector3 Offset = lcMul31(lcVector3(0.0f, 5.0f - 2.56f, 0.0f), Sections[SectionIdx]);
982
983 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
984 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
985
986 File.WriteBuffer(Line, strlen(Line));
987 }
988 }
989
AddTubeParts(lcLibraryMeshData & MeshData,const lcArray<lcMatrix44> & Sections,float Radius,bool IsInner)990 void lcSynthInfoCurved::AddTubeParts(lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections, float Radius, bool IsInner)
991 {
992 // a unit circle
993 static const lcVector3 Vertices[16] =
994 {
995 { 1.000000f, 0.0f, 0.000000f },
996 { 0.923880f, 0.0f, 0.382683f },
997 { 0.707107f, 0.0f, 0.707107f },
998 { 0.382683f, 0.0f, 0.923880f },
999 { 0.000000f, 0.0f, 1.000000f },
1000 { -0.382683f, 0.0f, 0.923880f },
1001 { -0.707107f, 0.0f, 0.707107f },
1002 { -0.923880f, 0.0f, 0.382683f },
1003 { -1.000000f, 0.0f, 0.000000f },
1004 { -0.923879f, 0.0f, -0.382684f },
1005 { -0.707107f, 0.0f, -0.707107f },
1006 { -0.382683f, 0.0f, -0.923880f },
1007 { 0.000000f, 0.0f, -1.000000f },
1008 { 0.382684f, 0.0f, -0.923879f },
1009 { 0.707107f, 0.0f, -0.707107f },
1010 { 0.923880f, 0.0f, -0.382683f },
1011 };
1012 const int NumSectionVertices = LC_ARRAY_COUNT(Vertices);
1013
1014 int BaseVertex;
1015 lcMeshLoaderVertex* VertexBuffer;
1016 quint32* IndexBuffer;
1017 MeshData.AddVertices(LC_MESHDATA_SHARED, NumSectionVertices * (Sections.GetSize() - 1), &BaseVertex, &VertexBuffer);
1018
1019 float NormalDirection = IsInner ? -1.0f : 1.0f;
1020
1021 for (int SectionIdx = 1; SectionIdx < Sections.GetSize(); SectionIdx++)
1022 {
1023 for (int VertexIdx = 0; VertexIdx < NumSectionVertices; VertexIdx++)
1024 {
1025 VertexBuffer->Position = lcMul31(Radius * Vertices[VertexIdx], Sections[SectionIdx]);
1026 VertexBuffer->Normal = lcMul30(NormalDirection * Vertices[VertexIdx], Sections[SectionIdx]);
1027 VertexBuffer->NormalWeight = 4.0f;
1028 VertexBuffer++;
1029 }
1030 }
1031
1032 MeshData.AddIndices(LC_MESHDATA_SHARED, LC_MESH_TRIANGLES, 16, 6 * NumSectionVertices * (Sections.GetSize() - 2), &IndexBuffer);
1033
1034 int Offset1, Offset2;
1035 if (IsInner)
1036 {
1037 Offset1 = NumSectionVertices - 1; // -1 mod NumVertices
1038 Offset2 = 0;
1039 }
1040 else
1041 {
1042 Offset1 = 0;
1043 Offset2 = 1;
1044 }
1045
1046 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
1047 {
1048 for (int VertexIdx = 0; VertexIdx < NumSectionVertices; VertexIdx++)
1049 {
1050 int Vertex1 = BaseVertex + (VertexIdx + Offset1) % NumSectionVertices;
1051 int Vertex2 = BaseVertex + (VertexIdx + Offset2) % NumSectionVertices;
1052
1053 *IndexBuffer++ = Vertex1;
1054 *IndexBuffer++ = Vertex2;
1055 *IndexBuffer++ = Vertex1 + NumSectionVertices;
1056 *IndexBuffer++ = Vertex2;
1057 *IndexBuffer++ = Vertex2 + NumSectionVertices;
1058 *IndexBuffer++ = Vertex1 + NumSectionVertices;
1059 }
1060 BaseVertex += NumSectionVertices;
1061 }
1062 }
1063
AddParts(lcMemFile & File,lcLibraryMeshData & MeshData,const lcArray<lcMatrix44> & Sections) const1064 void lcSynthInfoFlexSystemHose::AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const
1065 {
1066 char Line[256];
1067
1068 {
1069 const int SectionIdx = 0;
1070 lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(-1.0f, 1.0f, 1.0f)), lcMatrix33(Sections[SectionIdx])));
1071 lcVector3 Offset = lcMul31(lcVector3(0.0f, -1.0f, 0.0f), Sections[SectionIdx]);
1072
1073 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1074 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1075
1076 File.WriteBuffer(Line, strlen(Line));
1077 }
1078
1079 {
1080 const int SectionIdx = Sections.GetSize() - 1;
1081 lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(Sections[SectionIdx])));
1082 lcVector3 Offset = lcMul31(lcVector3(0.0f, 1.0f, 0.0f), Sections[SectionIdx]);
1083
1084 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1085 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1086
1087 File.WriteBuffer(Line, strlen(Line));
1088 }
1089
1090 AddTubeParts(MeshData, Sections, 4.0f, false);
1091 AddTubeParts(MeshData, Sections, 2.0f, true);
1092 }
1093
AddParts(lcMemFile & File,lcLibraryMeshData & MeshData,const lcArray<lcMatrix44> & Sections) const1094 void lcSynthInfoPneumaticTube::AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const
1095 {
1096 char Line[256];
1097
1098 {
1099 const int SectionIdx = 0;
1100 lcMatrix33 EdgeTransform(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, -1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f));
1101 lcMatrix33 Transform(lcMul(lcMul(EdgeTransform, lcMatrix33Scale(lcVector3(1.0f, 1.0f, 1.0f))), lcMatrix33(Sections[SectionIdx])));
1102 lcVector3 Offset = lcMul31(lcVector3(0.0f, 0.0f, 0.0f), Sections[SectionIdx]);
1103
1104 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1105 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2],
1106 mEndPart);
1107
1108 File.WriteBuffer(Line, strlen(Line));
1109 }
1110
1111 {
1112 const int SectionIdx = Sections.GetSize() - 1;
1113 lcMatrix33 EdgeTransform(lcVector3(0.0f, 0.0f, -1.0f), lcVector3(0.0f, -1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f));
1114 lcMatrix33 Transform(lcMul(lcMul(EdgeTransform, lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIdx])));
1115 lcVector3 Offset = lcMul31(lcVector3(0.0f, 0.0f, 0.0f), Sections[SectionIdx]);
1116
1117 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1118 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2],
1119 mEndPart);
1120
1121 File.WriteBuffer(Line, strlen(Line));
1122 }
1123
1124 AddTubeParts(MeshData, Sections, 5.0f, false);
1125 AddTubeParts(MeshData, Sections, 3.0f, true);
1126 }
1127
AddParts(lcMemFile & File,lcLibraryMeshData &,const lcArray<lcMatrix44> & Sections) const1128 void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcArray<lcMatrix44>& Sections) const
1129 {
1130 char Line[256];
1131
1132 {
1133 const int SectionIdx = 0;
1134 lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(Sections[SectionIdx])));
1135 lcVector3 Offset = Sections[SectionIdx].GetTranslation();
1136
1137 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1138 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1139
1140 File.WriteBuffer(Line, strlen(Line));
1141 }
1142
1143 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
1144 {
1145 const lcMatrix44& Transform = Sections[SectionIdx];
1146
1147 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 80.dat\n", Transform[3][0], Transform[3][1], Transform[3][2], Transform[0][0], Transform[1][0], Transform[2][0],
1148 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1149
1150 File.WriteBuffer(Line, strlen(Line));
1151 }
1152
1153 {
1154 const int SectionIdx = Sections.GetSize() - 1;
1155 lcMatrix33 Transform(Sections[SectionIdx]);
1156 lcVector3 Offset = lcMul31(lcVector3(0.0f, -6.25f, 0.0f), Sections[SectionIdx]);
1157
1158 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1159 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1160
1161 File.WriteBuffer(Line, strlen(Line));
1162 }
1163 }
1164
AddParts(lcMemFile & File,lcLibraryMeshData & MeshData,const lcArray<lcMatrix44> & Sections) const1165 void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const
1166 {
1167 char Line[256];
1168 const int NumEdgeParts = 6;
1169
1170 lcMatrix33 EdgeTransforms[6] =
1171 {
1172 lcMatrix33(lcVector3(-1.0f, 0.0f, 0.0f), lcVector3(0.0f, -5.0f, 0.0f), lcVector3(0.0f, 0.0f, 1.0f)),
1173 lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)),
1174 lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)),
1175 lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)),
1176 lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)),
1177 lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)),
1178 };
1179
1180 const char* EdgeParts[6] =
1181 {
1182 "stud3a.dat", "s/faxle1.dat", "s/faxle2.dat", "s/faxle3.dat", "s/faxle4.dat", "s/faxle5.dat"
1183 };
1184
1185 for (int PartIdx = 0; PartIdx < NumEdgeParts; PartIdx++)
1186 {
1187 const int SectionIdx = 0;
1188 lcMatrix33 Transform(lcMul(lcMul(EdgeTransforms[PartIdx], lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIdx])));
1189 lcVector3 Offset = lcMul31(lcVector3(0.0f, -4.0f * (5 - PartIdx), 0.0f), Sections[SectionIdx]);
1190
1191 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1192 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
1193
1194 File.WriteBuffer(Line, strlen(Line));
1195 }
1196
1197 for (int PartIdx = 0; PartIdx < NumEdgeParts; PartIdx++)
1198 {
1199 const int SectionIdx = Sections.GetSize() - 1;
1200 lcMatrix33 Transform(lcMul(EdgeTransforms[PartIdx], lcMatrix33(Sections[SectionIdx])));
1201 lcVector3 Offset = lcMul31(lcVector3(0.0f, 4.0f * (5 - PartIdx), 0.0f), Sections[SectionIdx]);
1202
1203 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1204 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
1205
1206 File.WriteBuffer(Line, strlen(Line));
1207 }
1208
1209 const lcMeshLoaderVertex SectionVertices[28] =
1210 {
1211 { lcVector3(-6.000f, 0.0f, 0.000f), lcVector3(-1.000f, 0.0f, 0.000f), 2.0f, lcVector2(0.0f, 0.0f), 0 },
1212 { lcVector3(-5.602f, 0.0f, 2.000f), lcVector3(-0.942f, 0.0f, 0.336f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1213 { lcVector3(-5.602f, 0.0f, 2.000f), lcVector3( 0.000f, 0.0f, 1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1214 { lcVector3(-2.000f, 0.0f, 2.000f), lcVector3( 0.000f, 0.0f, 1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1215 { lcVector3(-2.000f, 0.0f, 2.000f), lcVector3(-1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1216 { lcVector3(-2.000f, 0.0f, 5.602f), lcVector3(-1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1217 { lcVector3(-2.000f, 0.0f, 5.602f), lcVector3(-0.336f, 0.0f, 0.942f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1218 { lcVector3( 0.000f, 0.0f, 6.000f), lcVector3( 0.000f, 0.0f, 1.000f), 2.0f, lcVector2(0.0f, 0.0f), 0 },
1219 { lcVector3( 2.000f, 0.0f, 5.602f), lcVector3( 0.336f, 0.0f, 0.942f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1220 { lcVector3( 2.000f, 0.0f, 5.602f), lcVector3( 1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1221 { lcVector3( 2.000f, 0.0f, 2.000f), lcVector3( 1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1222 { lcVector3( 2.000f, 0.0f, 2.000f), lcVector3( 0.000f, 0.0f, 1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1223 { lcVector3( 5.602f, 0.0f, 2.000f), lcVector3( 0.000f, 0.0f, 1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1224 { lcVector3( 5.602f, 0.0f, 2.000f), lcVector3( 0.942f, 0.0f, 0.336f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1225 { lcVector3( 6.000f, 0.0f, 0.000f), lcVector3( 1.000f, 0.0f, 0.000f), 2.0f, lcVector2(0.0f, 0.0f), 0 },
1226 { lcVector3( 5.602f, 0.0f, -2.000f), lcVector3( 0.942f, 0.0f, -0.336f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1227 { lcVector3( 5.602f, 0.0f, -2.000f), lcVector3( 0.000f, 0.0f, -1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1228 { lcVector3( 2.000f, 0.0f, -2.000f), lcVector3( 0.000f, 0.0f, -1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1229 { lcVector3( 2.000f, 0.0f, -2.000f), lcVector3( 1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1230 { lcVector3( 2.000f, 0.0f, -5.602f), lcVector3( 1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1231 { lcVector3( 2.000f, 0.0f, -5.602f), lcVector3( 0.336f, 0.0f, -0.942f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1232 { lcVector3( 0.000f, 0.0f, -6.000f), lcVector3( 0.000f, 0.0f, -1.000f), 2.0f, lcVector2(0.0f, 0.0f), 0 },
1233 { lcVector3(-2.000f, 0.0f, -5.602f), lcVector3(-0.336f, 0.0f, -0.942f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1234 { lcVector3(-2.000f, 0.0f, -5.602f), lcVector3(-1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1235 { lcVector3(-2.000f, 0.0f, -2.000f), lcVector3(-1.000f, 0.0f, 0.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1236 { lcVector3(-2.000f, 0.0f, -2.000f), lcVector3( 0.000f, 0.0f, -1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1237 { lcVector3(-5.602f, 0.0f, -2.000f), lcVector3( 0.000f, 0.0f, -1.000f), 4.0f, lcVector2(0.0f, 0.0f), 0 },
1238 { lcVector3(-5.602f, 0.0f, -2.000f), lcVector3(-0.942f, 0.0f, -0.336f), 4.0f, lcVector2(0.0f, 0.0f), 0 }
1239 };
1240
1241 const int NumSectionVertices = LC_ARRAY_COUNT(SectionVertices);
1242
1243 int BaseVertex;
1244 lcMeshLoaderVertex* VertexBuffer;
1245 quint32* IndexBuffer;
1246 MeshData.AddVertices(LC_MESHDATA_SHARED, NumSectionVertices * (Sections.GetSize() - 1), &BaseVertex, &VertexBuffer);
1247 MeshData.AddIndices(LC_MESHDATA_SHARED, LC_MESH_LINES, 24, 2 * 12 * (Sections.GetSize() - 2), &IndexBuffer);
1248
1249 for (int SectionIdx = 1; SectionIdx < Sections.GetSize(); SectionIdx++)
1250 {
1251 for (int VertexIdx = 0; VertexIdx < NumSectionVertices; VertexIdx++)
1252 {
1253 VertexBuffer->Position = lcMul31(SectionVertices[VertexIdx].Position, Sections[SectionIdx]);
1254 VertexBuffer->Normal = lcMul30(SectionVertices[VertexIdx].Normal, Sections[SectionIdx]);
1255 VertexBuffer->NormalWeight = SectionVertices[VertexIdx].NormalWeight;
1256 VertexBuffer++;
1257 }
1258 }
1259
1260 int BaseLinesVertex = BaseVertex;
1261
1262 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
1263 {
1264 const int Indices[] = { 1, 3, 5, 8, 10, 12, 15, 17, 19, 22, 24, 26 };
1265
1266 for (int VertexIdx = 0; VertexIdx < 12; VertexIdx++)
1267 {
1268 *IndexBuffer++ = BaseLinesVertex + Indices[VertexIdx];
1269 *IndexBuffer++ = BaseLinesVertex + Indices[VertexIdx] + NumSectionVertices;
1270 }
1271
1272 BaseLinesVertex += NumSectionVertices;
1273 }
1274
1275 MeshData.AddIndices(LC_MESHDATA_SHARED, LC_MESH_TRIANGLES, 16, 6 * NumSectionVertices * (Sections.GetSize() - 2), &IndexBuffer);
1276
1277 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
1278 {
1279 for (int VertexIdx = 0; VertexIdx < NumSectionVertices; VertexIdx++)
1280 {
1281 int Vertex1 = BaseVertex + VertexIdx;
1282 int Vertex2 = BaseVertex + (VertexIdx + 1) % NumSectionVertices;
1283
1284 *IndexBuffer++ = Vertex1;
1285 *IndexBuffer++ = Vertex2;
1286 *IndexBuffer++ = Vertex1 + NumSectionVertices;
1287 *IndexBuffer++ = Vertex2;
1288 *IndexBuffer++ = Vertex2 + NumSectionVertices;
1289 *IndexBuffer++ = Vertex1 + NumSectionVertices;
1290 }
1291 BaseVertex += NumSectionVertices;
1292 }
1293 }
1294
AddParts(lcMemFile & File,lcLibraryMeshData & MeshData,const lcArray<lcMatrix44> & SectionsIn) const1295 void lcSynthInfoBraidedString::AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& SectionsIn) const
1296 {
1297 lcArray<lcMatrix44> Sections;
1298 Sections.SetSize(SectionsIn.GetSize());
1299
1300 for (int SectionIdx = 0; SectionIdx < Sections.GetSize(); SectionIdx++)
1301 {
1302 lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(SectionsIn[SectionIdx])));
1303 lcVector3 Offset = SectionsIn[SectionIdx].GetTranslation();
1304 Sections[SectionIdx] = lcMatrix44(Transform, Offset);
1305 }
1306
1307 char Line[256];
1308
1309 {
1310 const int SectionIdx = 0;
1311 lcMatrix33 Transform(Sections[SectionIdx]);
1312 lcVector3 Offset = lcMul31(lcVector3(-8.0f, 0.0f, 0.0f), Sections[SectionIdx]);
1313
1314 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1315 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1316
1317 File.WriteBuffer(Line, strlen(Line));
1318 }
1319
1320 const int NumSegments = 16;
1321 const int NumBraids = 4;
1322 const float PositionTable[16] =
1323 {
1324 -1.5f, -1.386f, -1.061f, -0.574f, 0.0f, 0.574f, 1.061f, 1.386f, 1.5f, 1.386f, 1.061f, 0.574f, 0.0f, -0.574f, -1.061f, -1.386f
1325 };
1326
1327 int BaseVertex;
1328 lcMeshLoaderVertex* VertexBuffer;
1329 quint32* IndexBuffer;
1330 MeshData.AddVertices(LC_MESHDATA_SHARED, NumBraids * ((Sections.GetSize() - 2) * NumSegments + 1), &BaseVertex, &VertexBuffer);
1331 MeshData.AddIndices(LC_MESHDATA_SHARED, LC_MESH_LINES, 24, NumBraids * (Sections.GetSize() - 2) * NumSegments * 2, &IndexBuffer);
1332
1333 for (int BraidIdx = 0; BraidIdx < NumBraids; BraidIdx++)
1334 {
1335 int BaseX = (BraidIdx == 0 || BraidIdx == 2) ? 0 : 8;
1336 int BaseY = (BraidIdx == 0 || BraidIdx == 3) ? 12 : 4;
1337
1338 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
1339 {
1340 lcMatrix33 Transform1 = lcMatrix33(Sections[SectionIdx]);
1341 lcMatrix33 Transform2 = lcMatrix33(Sections[SectionIdx + 1]);
1342 lcVector3 Offset1 = Sections[SectionIdx].GetTranslation();
1343 lcVector3 Offset2 = Sections[SectionIdx + 1].GetTranslation();
1344
1345 for (int SegmentIdx = 0; SegmentIdx < ((SectionIdx < Sections.GetSize() - 2) ? NumSegments : NumSegments + 1); SegmentIdx++)
1346 {
1347 float t = (float)SegmentIdx / (float)NumSegments;
1348
1349 lcVector3 Vertex1 = lcVector3(t * 4.0f, PositionTable[(BaseX + SegmentIdx) % NumSegments], PositionTable[(BaseY + SegmentIdx) % NumSegments]) + lcVector3(0.0f, 1.5f, 0.0f);
1350 lcVector3 Vertex2 = lcVector3((1.0f - t) * -4.0f, PositionTable[(BaseX + SegmentIdx) % NumSegments], PositionTable[(BaseY + SegmentIdx) % NumSegments]) + lcVector3(0.0f, 1.5f, 0.0f);
1351
1352 lcVector3 Vertex = (lcMul(Vertex1, Transform1) + Offset1) * (1.0f - t) + (lcMul(Vertex2, Transform2) + Offset2) * t;
1353
1354 VertexBuffer->Position = Vertex;
1355 VertexBuffer->Normal = lcVector3(0.0f, 0.0f, 0.0f);
1356 VertexBuffer->NormalWeight = 0.0f;
1357 VertexBuffer++;
1358
1359 if (SegmentIdx != NumSegments)
1360 {
1361 *IndexBuffer++ = BaseVertex;
1362 *IndexBuffer++ = BaseVertex + 1;
1363 BaseVertex++;
1364 }
1365 }
1366 }
1367
1368 BaseVertex++;
1369 }
1370
1371 int NumSlices = 16;
1372 MeshData.AddVertices(LC_MESHDATA_SHARED, NumSlices * ((Sections.GetSize() - 2) * NumSegments + 1), &BaseVertex, &VertexBuffer);
1373 MeshData.AddIndices(LC_MESHDATA_SHARED, LC_MESH_TRIANGLES, 16, NumSlices * (Sections.GetSize() - 2) * NumSegments * 6, &IndexBuffer);
1374
1375 for (int SectionIdx = 1; SectionIdx < Sections.GetSize() - 1; SectionIdx++)
1376 {
1377 lcMatrix33 Transform1 = lcMatrix33(Sections[SectionIdx]);
1378 lcMatrix33 Transform2 = lcMatrix33(Sections[SectionIdx + 1]);
1379 lcVector3 Offset1 = Sections[SectionIdx].GetTranslation();
1380 lcVector3 Offset2 = Sections[SectionIdx + 1].GetTranslation();
1381
1382 for (int SegmentIdx = 0; SegmentIdx < ((SectionIdx < Sections.GetSize() - 2) ? NumSegments : NumSegments + 1); SegmentIdx++)
1383 {
1384 float t1 = (float)SegmentIdx / (float)NumSegments;
1385 int BaseX = 8;
1386 int BaseY = 4;
1387
1388 for (int SliceIdx = 0; SliceIdx < NumSlices; SliceIdx++)
1389 {
1390 lcVector3 Vertex11 = lcVector3(t1 * 4.0f, PositionTable[(BaseX + SliceIdx) % NumSlices], PositionTable[(BaseY + SliceIdx) % NumSlices]) + lcVector3(0.0f, 1.5f, 0.0f);
1391 lcVector3 Vertex12 = lcVector3((1.0f - t1) * -4.0f, PositionTable[(BaseX + SliceIdx) % NumSlices], PositionTable[(BaseY + SliceIdx) % NumSlices]) + lcVector3(0.0f, 1.5f, 0.0f);
1392 VertexBuffer->Position = (lcMul(Vertex11, Transform1) + Offset1) * (1.0f - t1) + (lcMul(Vertex12, Transform2) + Offset2) * t1;
1393
1394 lcVector3 Normal11 = lcVector3(0.0f, PositionTable[(BaseX + SliceIdx) % NumSlices] / 1.5f, PositionTable[(BaseY + SliceIdx) % NumSlices] / 1.5f);
1395 lcVector3 Normal12 = lcVector3(0.0f, PositionTable[(BaseX + SliceIdx) % NumSlices] / 1.5f, PositionTable[(BaseY + SliceIdx) % NumSlices] / 1.5f);
1396 VertexBuffer->Normal = lcMul(Normal11, Transform1) * (1.0f - t1) + lcMul(Normal12, Transform2) * t1;
1397 VertexBuffer->NormalWeight = 1.0f;
1398 VertexBuffer++;
1399
1400 if (SegmentIdx != NumSegments)
1401 {
1402 *IndexBuffer++ = BaseVertex + SliceIdx;
1403 *IndexBuffer++ = BaseVertex + (SliceIdx + 1) % NumSlices;
1404 *IndexBuffer++ = BaseVertex + (SliceIdx + 1) % NumSlices + NumSlices;
1405
1406 *IndexBuffer++ = BaseVertex + SliceIdx + NumSlices;
1407 *IndexBuffer++ = BaseVertex + SliceIdx;
1408 *IndexBuffer++ = BaseVertex + (SliceIdx + 1) % NumSlices + NumSlices;
1409 }
1410 }
1411
1412 BaseVertex += NumSlices;
1413 }
1414 }
1415
1416 {
1417 const int SectionIdx = Sections.GetSize() - 1;
1418 lcMatrix33 Transform(Sections[SectionIdx]);
1419 lcVector3 Offset = lcMul31(lcVector3(8.0f, 0.0f, 0.0f), Sections[SectionIdx]);
1420
1421 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
1422 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
1423
1424 File.WriteBuffer(Line, strlen(Line));
1425 }
1426 }
1427
AddParts(lcMemFile & File,lcLibraryMeshData &,const lcArray<lcMatrix44> & Sections) const1428 void lcSynthInfoShockAbsorber::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcArray<lcMatrix44>& Sections) const
1429 {
1430 char Line[256];
1431 lcVector3 Offset;
1432
1433 Offset = Sections[0].GetTranslation();
1434 sprintf(Line, "1 0 %f %f %f 1 0 0 0 1 0 0 0 1 4254.dat\n", Offset[0], Offset[1], Offset[2]);
1435 File.WriteBuffer(Line, strlen(Line));
1436
1437 Offset = Sections[1].GetTranslation();
1438 sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 4255.dat\n", Offset[0], Offset[1], Offset[2]);
1439 File.WriteBuffer(Line, strlen(Line));
1440
1441 float Distance = Sections[0].GetTranslation().y - Sections[1].GetTranslation().y;
1442 float Scale = (Distance - 66.0f) / 44.0f;
1443
1444 Offset = Sections[0].GetTranslation();
1445 sprintf(Line, "1 494 %f %f %f 1 0 0 0 %f 0 0 0 1 %s\n", Offset[0], Offset[1] - 10 - 44.0f * Scale, Offset[2], Scale, mSpringPart);
1446 File.WriteBuffer(Line, strlen(Line));
1447 }
1448
AddParts(lcMemFile & File,lcLibraryMeshData &,const lcArray<lcMatrix44> & Sections) const1449 void lcSynthInfoActuator::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcArray<lcMatrix44>& Sections) const
1450 {
1451 char Line[256];
1452 lcVector3 Offset;
1453
1454 Offset = Sections[0].GetTranslation();
1455 sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mBodyPart);
1456 File.WriteBuffer(Line, strlen(Line));
1457
1458 Offset = lcMul(Sections[0], lcMatrix44Translation(lcVector3(0.0f, 0.0f, mAxleOffset))).GetTranslation();
1459 sprintf(Line, "1 25 %f %f %f 0 1 0 -1 0 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mAxlePart);
1460 File.WriteBuffer(Line, strlen(Line));
1461
1462 Offset = Sections[1].GetTranslation();
1463 sprintf(Line, "1 72 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mPistonPart);
1464 File.WriteBuffer(Line, strlen(Line));
1465 }
1466
AddParts(lcMemFile & File,lcLibraryMeshData &,const lcArray<lcMatrix44> & Sections) const1467 void lcSynthInfoUniversalJoint::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcArray<lcMatrix44>& Sections) const
1468 {
1469 char Line[256];
1470 lcVector3 Offset = Sections[0].GetTranslation();
1471
1472 float Angle = atan2f(Offset.x, Offset.z);
1473 lcMatrix44 Rotation = lcMatrix44RotationZ(Angle);
1474 lcMatrix44 Transform = lcMatrix44LeoCADToLDraw(Rotation);
1475
1476 sprintf(Line, "1 16 0 0 0 %f %f %f %f %f %f %f %f %f %s\n", Transform[0][0], Transform[1][0], Transform[2][0],
1477 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mCenterPart);
1478 File.WriteBuffer(Line, strlen(Line));
1479
1480 Angle = atan2f(Offset.y, hypotf(Offset.x, Offset.z));
1481 Rotation = lcMul(Rotation, lcMatrix44RotationX(Angle));
1482 Transform = lcMul(
1483 lcMatrix44Translation(lcVector3(0.0f, 0.0f, mEndOffset)),
1484 lcMatrix44LeoCADToLDraw(Rotation)
1485 );
1486
1487 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2],
1488 Transform[0][0], Transform[1][0], Transform[2][0],
1489 Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
1490 File.WriteBuffer(Line, strlen(Line));
1491
1492 Rotation = lcMatrix44FromEulerAngles(lcVector3(0.0f, LC_PI/2, LC_PI));
1493 Transform = lcMatrix44LeoCADToLDraw(lcMul(lcMatrix44Translation(lcVector3(0.0f, mEndOffset, 0.0f)), Rotation));
1494 sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2],
1495 Transform[0][0], Transform[1][0], Transform[2][0],
1496 Transform[0][1], Transform[1][1], -Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
1497 File.WriteBuffer(Line, strlen(Line));
1498 }
1499
CreateMesh(const lcArray<lcPieceControlPoint> & ControlPoints) const1500 lcMesh* lcSynthInfo::CreateMesh(const lcArray<lcPieceControlPoint>& ControlPoints) const
1501 {
1502 lcArray<lcMatrix44> Sections;
1503
1504 CalculateSections(ControlPoints, Sections, nullptr);
1505
1506 lcLibraryMeshData MeshData;
1507 lcMemFile File; // todo: rewrite this to pass the parts directly
1508
1509 AddParts(File, MeshData, Sections);
1510
1511 File.WriteU8(0);
1512
1513 lcArray<lcMeshLoaderTextureMap> TextureStack;
1514 File.Seek(0, SEEK_SET);
1515
1516 lcMeshLoader MeshLoader(MeshData, false, nullptr, false);
1517 if (MeshLoader.LoadMesh(File, LC_MESHDATA_SHARED))
1518 return MeshData.CreateMesh();
1519
1520 return nullptr;
1521 }
1522
InsertControlPoint(lcArray<lcPieceControlPoint> & ControlPoints,const lcVector3 & Start,const lcVector3 & End) const1523 int lcSynthInfo::InsertControlPoint(lcArray<lcPieceControlPoint>& ControlPoints, const lcVector3& Start, const lcVector3& End) const
1524 {
1525 lcArray<lcMatrix44> Sections;
1526
1527 int BestSegment = -1;
1528 float BestTime;
1529 float BestDistance = FLT_MAX;
1530 lcVector3 BestPosition;
1531
1532 CalculateSections(ControlPoints, Sections,
1533 [&](const lcVector3& CurvePoint, int SegmentIndex, float t)
1534 {
1535 float Distance = lcRayPointDistance(CurvePoint, Start, End);
1536 if (Distance < BestDistance)
1537 {
1538 BestSegment = SegmentIndex;
1539 BestTime = t;
1540 BestDistance = Distance;
1541 BestPosition = lcVector3LDrawToLeoCAD(CurvePoint);
1542 }
1543 }
1544 );
1545
1546 if (BestSegment != -1)
1547 {
1548 lcPieceControlPoint ControlPoint = ControlPoints[BestSegment];
1549 ControlPoint.Transform.SetTranslation(BestPosition);
1550
1551 if (BestSegment != ControlPoints.GetSize() - 1)
1552 {
1553 lcPieceControlPoint NextControlPoint = ControlPoints[BestSegment + 1];
1554 ControlPoint.Scale = ControlPoint.Scale * (1.0f - BestTime) + NextControlPoint.Scale * BestTime;
1555 }
1556
1557 ControlPoints.InsertAt(BestSegment + 1, ControlPoint);
1558 }
1559
1560 return BestSegment + 1;
1561 }
1562