Synthesis of Technic Universal Joints (#456)

* Split synth info initialzation by type.

We are going to remove the type enumeration and use a class hierarchy
instead. This preparation will then be helpful.

* Make Add...Parts() overrides of a virtual AddPart() function.

Since we have a class hierarchy for the different synthesized pieces, we
can now turn a case distinction into a virtual function call.

* Move initialization based on type to derived class constructors.

Move initialization of end transformations of flexible parts into
class lcSynthInfoCurved.

* Make GetDefaultControlPoints() virtual with overrides.

* Remove obsolete enum lcSynthType.

We have replaced its purpose by derived classes by now.

* Initialize shock absorbers' spring part ID early.

This removes the awkward early return that is needed in the if-else
cascade.

* Split lcSynthInfo into derived classes for curved and straight pieces.

* Only curved parts have varying sections, start, middle, and end properties.

Move the properties from the base class to the derived class that needs
them.

* Use derived classes to mark synthesized objects of different kinds.

We will extend the derived classes in the upcoming commits.

* PieceInfo is only needed to synthesize some hoses and shock absorbers.

* Initialize edge part IDs of flexible hoses early.

This removes another case distinction in AddParts().

* Verify the number of control points loaded from a model file.

* Synthesize Technic universal joints.

The direction of one end can be changed so that it points to the control
point.

* Technic universal joints need only the position of the control point.

* Synthesize legacy universal joints.
This commit is contained in:
Johannes Sixt 2020-03-30 21:17:08 +02:00 committed by GitHub
parent b9662dd3e0
commit ca73f3e3ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 729 additions and 365 deletions

View file

@ -684,6 +684,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project)
Piece->SetPieceInfo(Info, PartId, false);
Piece->Initialize(Transform, CurrentStep);
Piece->SetColorCode(ColorCode);
Piece->VerifyControlPoints(ControlPoints);
Piece->SetControlPoints(ControlPoints);
AddPiece(Piece);
Piece = nullptr;

File diff suppressed because it is too large Load diff

View file

@ -3,29 +3,13 @@
#include "lc_math.h"
#include "piece.h"
enum class lcSynthType
{
HOSE_FLEXIBLE,
FLEX_SYSTEM_HOSE,
RIBBED_HOSE,
FLEXIBLE_AXLE,
STRING_BRAIDED,
SHOCK_ABSORBER,
ACTUATOR
};
struct lcSynthComponent
{
lcMatrix44 Transform;
float Length;
};
class lcLibraryMeshData;
class lcSynthInfo
{
public:
lcSynthInfo(lcSynthType Type, float Length, int NumSections, PieceInfo* Info);
explicit lcSynthInfo(float Length);
virtual ~lcSynthInfo() = default;
bool CanAddControlPoints() const
{
@ -37,33 +21,30 @@ public:
return mCurve;
}
void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const;
bool IsUnidirectional() const
{
return mUnidirectional;
}
bool IsNondirectional() const
{
return mNondirectional;
}
virtual void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const = 0;
virtual void VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const = 0;
int InsertControlPoint(lcArray<lcPieceControlPoint>& ControlPoints, const lcVector3& Start, const lcVector3& End) const;
lcMesh* CreateMesh(const lcArray<lcPieceControlPoint>& ControlPoints) const;
protected:
float GetSectionTwist(const lcMatrix44& StartTransform, const lcMatrix44& EndTransform) const;
using SectionCallbackFunc = std::function<void(const lcVector3& CurvePoint, int SegmentIndex, float t)>;
void CalculateCurveSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const;
void CalculateLineSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const;
void AddHoseFlexibleParts(lcMemFile& File, const lcArray<lcMatrix44>& Sections) const;
void AddFlexHoseParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const;
void AddRibbedHoseParts(lcMemFile& File, const lcArray<lcMatrix44>& Sections) const;
void AddFlexibleAxleParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const;
void AddStringBraidedParts(lcMemFile& File, lcLibraryMeshData& MeshData, lcArray<lcMatrix44>& Sections) const;
void AddShockAbsorberParts(lcMemFile& File, lcArray<lcMatrix44>& Sections) const;
void AddActuatorParts(lcMemFile& File, lcArray<lcMatrix44>& Sections) const;
virtual void CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, SectionCallbackFunc SectionCallback) const = 0;
virtual void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const = 0;
PieceInfo* mPieceInfo;
lcSynthType mType;
lcSynthComponent mStart;
lcSynthComponent mMiddle;
lcSynthComponent mEnd;
bool mCurve;
bool mCurve = false;
bool mUnidirectional = false;
bool mNondirectional = false;
float mLength;
float mCenterLength;
int mNumSections;
bool mRigidEdges;
};
void lcSynthInit();

View file

@ -797,19 +797,27 @@ void lcPiece::RotatePivotPoint(const lcMatrix33& RotationMatrix)
quint32 lcPiece::GetAllowedTransforms() const
{
const quint32 Move = LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z;
const quint32 Rotate = LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z;
quint32 Section = GetFocusSection();
if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID)
return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z | LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z;
return Move | Rotate;
lcSynthInfo* SynthInfo = mPieceInfo->GetSynthInfo();
if (!SynthInfo)
return 0;
if (SynthInfo)
{
if (SynthInfo->IsUnidirectional())
return LC_OBJECT_TRANSFORM_MOVE_Z;
if (SynthInfo->IsCurve())
return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z | LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z | LC_OBJECT_TRANSFORM_SCALE_X;
else
return LC_OBJECT_TRANSFORM_MOVE_Z;
if (SynthInfo->IsCurve())
return Move | Rotate | LC_OBJECT_TRANSFORM_SCALE_X;
if (SynthInfo->IsNondirectional())
return Move;
}
return 0;
}
bool lcPiece::CanAddControlPoint() const
@ -866,6 +874,22 @@ bool lcPiece::RemoveFocusedControlPoint()
return true;
}
void lcPiece::VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const
{
lcSynthInfo* SynthInfo = mPieceInfo->GetSynthInfo();
if (!SynthInfo)
{
ControlPoints.RemoveAll();
}
else
{
if (ControlPoints.GetSize() > LC_MAX_CONTROL_POINTS)
ControlPoints.SetSize(LC_MAX_CONTROL_POINTS);
SynthInfo->VerifyControlPoints(ControlPoints);
}
}
const char* lcPiece::GetName() const
{
return mPieceInfo->m_strDescription;

View file

@ -431,11 +431,8 @@ public:
void SetControlPoints(const lcArray<lcPieceControlPoint>& ControlPoints)
{
if (ControlPoints.GetSize() > 1)
{
mControlPoints = ControlPoints;
UpdateMesh();
}
mControlPoints = ControlPoints;
UpdateMesh();
}
void SetControlPointScale(int ControlPointIndex, float Scale)
@ -472,6 +469,7 @@ public:
bool InsertControlPoint(const lcVector3& WorldStart, const lcVector3& WorldEnd);
bool RemoveFocusedControlPoint();
void VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const;
lcGroup* GetTopGroup();