Added options to add and remove control points.

This commit is contained in:
leo
2016-03-03 00:04:49 +00:00
parent 1cd4a8cee0
commit b5233f714c
12 changed files with 264 additions and 45 deletions
+14
View File
@@ -956,6 +956,20 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
QT_TRANSLATE_NOOP("Status", "Reset the pivot point of the selected pieces to their origin"),
QT_TRANSLATE_NOOP("Shortcut", "")
},
// LC_PIECE_CONTROL_POINT_INSERT
{
"Piece.ControlPoint.Insert",
QT_TRANSLATE_NOOP("Menu", "Insert Control Point"),
QT_TRANSLATE_NOOP("Status", "Insert a new control point"),
QT_TRANSLATE_NOOP("Shortcut", "")
},
// LC_PIECE_CONTROL_POINT_REMOVE
{
"Piece.ControlPoint.Remove",
QT_TRANSLATE_NOOP("Menu", "Remove Control Point"),
QT_TRANSLATE_NOOP("Status", "Remove the currently selected control point"),
QT_TRANSLATE_NOOP("Shortcut", "")
},
// LC_PIECE_MOVE_PLUSX
{
"Piece.Move.PlusX",
+2
View File
@@ -147,6 +147,8 @@ enum lcCommandId
LC_PIECE_INSERT,
LC_PIECE_DELETE,
LC_PIECE_RESET_PIVOT_POINT,
LC_PIECE_CONTROL_POINT_INSERT,
LC_PIECE_CONTROL_POINT_REMOVE,
LC_PIECE_MOVE_PLUSX,
LC_PIECE_MOVE_MINUSX,
LC_PIECE_MOVE_PLUSY,
+10
View File
@@ -1487,6 +1487,8 @@ void lcMainWindow::UpdateSelectedObjects(bool SelectionChanged)
mActions[LC_PIECE_DELETE]->setEnabled(Flags & LC_SEL_SELECTED);
mActions[LC_PIECE_RESET_PIVOT_POINT]->setEnabled(Flags & LC_SEL_SELECTED);
mActions[LC_PIECE_ARRAY]->setEnabled(Flags & LC_SEL_PIECE);
mActions[LC_PIECE_CONTROL_POINT_INSERT]->setEnabled(Flags & LC_SEL_CAN_ADD_CONTROL_POINT);
mActions[LC_PIECE_CONTROL_POINT_REMOVE]->setEnabled(Flags & LC_SEL_CAN_REMOVE_CONTROL_POINT);
mActions[LC_PIECE_HIDE_SELECTED]->setEnabled(Flags & LC_SEL_VISIBLE_SELECTED);
mActions[LC_PIECE_HIDE_UNSELECTED]->setEnabled(Flags & LC_SEL_UNSELECTED);
mActions[LC_PIECE_UNHIDE_SELECTED]->setEnabled(Flags & LC_SEL_HIDDEN_SELECTED);
@@ -2092,6 +2094,14 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
lcGetActiveModel()->ResetSelectedPiecesPivotPoint();
break;
case LC_PIECE_CONTROL_POINT_INSERT:
lcGetActiveModel()->InsertControlPoint();
break;
case LC_PIECE_CONTROL_POINT_REMOVE:
lcGetActiveModel()->RemoveFocusedControlPoint();
break;
case LC_PIECE_MOVE_PLUSX:
lcGetActiveModel()->MoveSelectedObjects(mActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true);
break;
+37 -15
View File
@@ -521,6 +521,11 @@ inline lcVector4& operator/=(lcVector4& a, float b)
return a;
}
inline lcVector3 lcVector3LDrawToLeoCAD(const lcVector3& Vector)
{
return lcVector3(Vector[0], Vector[2], -Vector[1]);
}
inline lcVector3 lcVector3FromColor(lcuint32 Color)
{
lcVector3 v(LC_RGBA_RED(Color), LC_RGBA_GREEN(Color), LC_RGBA_BLUE(Color));
@@ -1242,6 +1247,30 @@ inline lcMatrix44 lcMatrix44Inverse(const lcMatrix44& m)
#undef SWAP_ROWS
}
inline lcMatrix44 lcMatrix44LeoCADToLDraw(const lcMatrix44& Matrix)
{
lcMatrix44 m;
m.r[0] = lcVector4(Matrix[0][0], -Matrix[2][0], Matrix[1][0], 0.0f);
m.r[1] = lcVector4(-Matrix[0][2], Matrix[2][2], -Matrix[1][2], 0.0f);
m.r[2] = lcVector4(Matrix[0][1], -Matrix[2][1], Matrix[1][1], 0.0f);
m.r[3] = lcVector4(Matrix[3][0], -Matrix[3][2], Matrix[3][1], 1.0f);
return m;
}
inline lcMatrix44 lcMatrix44LDrawToLeoCAD(const lcMatrix44& Matrix)
{
lcMatrix44 m;
m.r[0] = lcVector4(Matrix[0][0], Matrix[2][0], -Matrix[1][0], 0.0f);
m.r[1] = lcVector4(Matrix[0][2], Matrix[2][2], -Matrix[1][2], 0.0f);
m.r[2] = lcVector4(-Matrix[0][1], -Matrix[2][1], Matrix[1][1], 0.0f);
m.r[3] = lcVector4(Matrix[3][0], Matrix[3][2], -Matrix[3][1], 1.0f);
return m;
}
inline lcVector4 lcQuaternionRotationX(float Radians)
{
return lcVector4(sinf(Radians / 2.0f), 0, 0, cosf(Radians / 2.0f));
@@ -1760,26 +1789,19 @@ inline bool lcSphereRayMinIntersectDistance(const lcVector3& Center, float Radiu
}
}
/*
float LinePointMinDistance(const Vector3& Point, const Vector3& Start, const Vector3& End)
inline float lcRayPointDistance(const lcVector3& Point, const lcVector3& Start, const lcVector3& End)
{
Vector3 Dir = End - Start;
lcVector3 Dir = Point - Start;
lcVector3 RayDir = End - Start;
float t1 = Dot3(Start - Point, Dir);
float t2 = LengthSquared(Dir);
float t = lcDot(Dir, RayDir) / lcLengthSquared(RayDir);
t = lcClamp(t, 0.0f, 1.0f);
float t = -t1 / t2;
lcVector3 Closest = Start + t * RayDir;
if (t < 0.0f)
t = 0.0f;
else if (t > 1.0f)
t = 1.0f;
Vector3 Closest = Start + t * Dir;
return Length(Closest - Point);
return lcLength(Closest - Point);
}
*/
// Returns true if the axis aligned box intersects the volume defined by planes.
inline bool lcBoundingBoxIntersectsVolume(const lcVector3& Min, const lcVector3& Max, const lcVector4 Planes[6])
{
+47
View File
@@ -1918,6 +1918,43 @@ void lcModel::ResetSelectedPiecesPivotPoint()
gMainWindow->UpdateAllViews();
}
void lcModel::InsertControlPoint()
{
lcObject* Focus = GetFocusObject();
if (!Focus || !Focus->IsPiece())
return;
lcPiece* Piece = (lcPiece*)Focus;
lcVector3 Start, End;
gMainWindow->GetActiveView()->GetRayUnderPointer(Start, End);
if (Piece->InsertControlPoint(Start, End))
{
SaveCheckpoint("Modifying");
gMainWindow->UpdateSelectedObjects(true);
gMainWindow->UpdateAllViews();
}
}
void lcModel::RemoveFocusedControlPoint()
{
lcObject* Focus = GetFocusObject();
if (!Focus || !Focus->IsPiece())
return;
lcPiece* Piece = (lcPiece*)Focus;
if (Piece->RemoveFocusedControlPoint())
{
SaveCheckpoint("Modifying");
gMainWindow->UpdateSelectedObjects(true);
gMainWindow->UpdateAllViews();
}
}
void lcModel::ShowSelectedPiecesEarlier()
{
lcArray<lcPiece*> MovedPieces;
@@ -2910,6 +2947,16 @@ void lcModel::GetSelectionInformation(int* Flags, lcArray<lcObject*>& Selection,
*Flags |= LC_SEL_PIECE | LC_SEL_SELECTED;
if (Piece->mPieceInfo->GetSynthInfo())
{
*Flags |= LC_SEL_CAN_ADD_CONTROL_POINT;
lcuint32 Section = Piece->GetFocusSection();
if (Section >= LC_PIECE_SECTION_CONTROL_POINT_1 && Section <= LC_PIECE_SECTION_CONTROL_POINT_8 && Piece->GetControlPoints().GetSize() > 2)
*Flags |= LC_SEL_CAN_REMOVE_CONTROL_POINT;
}
if (Piece->GetGroup() != NULL)
{
*Flags |= LC_SEL_GROUPED;
+15 -11
View File
@@ -5,17 +5,19 @@
#include "lc_math.h"
#include "object.h"
#define LC_SEL_NO_PIECES 0x001 // No pieces in model
#define LC_SEL_PIECE 0x002 // At last 1 piece selected
#define LC_SEL_SELECTED 0x004 // At last 1 object selected
#define LC_SEL_UNSELECTED 0x008 // At least 1 piece unselected
#define LC_SEL_HIDDEN 0x010 // At least one piece hidden
#define LC_SEL_HIDDEN_SELECTED 0x020 // At least one piece selected is hidden
#define LC_SEL_VISIBLE_SELECTED 0x040 // At least one piece selected is not hidden
#define LC_SEL_GROUPED 0x080 // At least one piece selected is grouped
#define LC_SEL_FOCUS_GROUPED 0x100 // Focused piece is grouped
#define LC_SEL_CAN_GROUP 0x200 // Can make a new group
#define LC_SEL_MODEL_SELECTED 0x400 // At least one model reference is selected
#define LC_SEL_NO_PIECES 0x0001 // No pieces in model
#define LC_SEL_PIECE 0x0002 // At last 1 piece selected
#define LC_SEL_SELECTED 0x0004 // At last 1 object selected
#define LC_SEL_UNSELECTED 0x0008 // At least 1 piece unselected
#define LC_SEL_HIDDEN 0x0010 // At least one piece hidden
#define LC_SEL_HIDDEN_SELECTED 0x0020 // At least one piece selected is hidden
#define LC_SEL_VISIBLE_SELECTED 0x0040 // At least one piece selected is not hidden
#define LC_SEL_GROUPED 0x0080 // At least one piece selected is grouped
#define LC_SEL_FOCUS_GROUPED 0x0100 // Focused piece is grouped
#define LC_SEL_CAN_GROUP 0x0200 // Can make a new group
#define LC_SEL_MODEL_SELECTED 0x0400 // At least one model reference is selected
#define LC_SEL_CAN_ADD_CONTROL_POINT 0x0800 // Can add control points to focused piece
#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece
enum lcTransformType
{
@@ -197,6 +199,8 @@ public:
void DeleteAllCameras();
void DeleteSelectedObjects();
void ResetSelectedPiecesPivotPoint();
void InsertControlPoint();
void RemoveFocusedControlPoint();
void ShowSelectedPiecesEarlier();
void ShowSelectedPiecesLater();
void SetPieceSteps(const QList<QPair<lcPiece*, lcStep>>& PieceSteps);
+72 -18
View File
@@ -56,26 +56,13 @@ void lcSynthInit()
}
}
inline lcMatrix44 lcMatrix44LeoCADToLDraw(const lcMatrix44& Matrix)
{
lcMatrix44 m;
m.r[0] = lcVector4( Matrix[0][0], -Matrix[2][0], Matrix[1][0], 0.0f);
m.r[1] = lcVector4(-Matrix[0][2], Matrix[2][2], -Matrix[1][2], 0.0f);
m.r[2] = lcVector4( Matrix[0][1], -Matrix[2][1], Matrix[1][1], 0.0f);
m.r[3] = lcVector4( Matrix[3][0], -Matrix[3][2], Matrix[3][1], 1.0f);
return m;
}
#include "lc_file.h"
lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPoint>& ControlPoints)
static void lcSynthEvaluate(const lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, void (*SectionCallback)(const lcVector3& CurvePoint, int SegmentIndex, float t, void* Param), void* CallbackParam)
{
lcArray<lcMatrix44> Sections;
float SectionLength = 0.0f;
for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize() - 1; ControlPointIdx++)
for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize() - 1 && Sections.GetSize() < SynthInfo->NumSections + 2; ControlPointIdx++)
{
lcVector3 SegmentControlPoints[4];
@@ -84,13 +71,13 @@ lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPo
if (ControlPointIdx == 0)
{
StartTransform = lcMul(StartTransform, SynthInfo->Components[0].Transform);
StartTransform = lcMatrix44(lcMul(lcMatrix33(StartTransform), lcMatrix33(SynthInfo->Components[0].Transform)), StartTransform.GetTranslation());
Sections.Add(StartTransform);
SectionLength = SynthInfo->Components[0].Length;
}
if (ControlPointIdx == ControlPoints.GetSize() - 2)
EndTransform = lcMul(EndTransform, lcMatrix44(lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, -1.0f, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f)));
EndTransform = lcMatrix44(lcMul(lcMatrix33(EndTransform), lcMatrix33(lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, -1.0f, 0.0f), lcVector3(0.0f, 0.0f, 1.0f))), EndTransform.GetTranslation());
SegmentControlPoints[0] = StartTransform.GetTranslation();
SegmentControlPoints[1] = lcMul31(lcVector3(0.0f, ControlPoints[ControlPointIdx].Stiffness, 0.0f), StartTransform);
@@ -159,6 +146,9 @@ lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPo
Sections.Add(lcMatrix44(lcMatrix33(lcNormalize(Up), lcNormalize(Tangent), lcNormalize(Side)), CurvePoints[CurrentPointIndex]));
if (SectionCallback)
SectionCallback(CurvePoints[CurrentPointIndex], ControlPointIdx, t, CallbackParam);
if (Sections.GetSize() == SynthInfo->NumSections + 2)
break;
@@ -172,16 +162,25 @@ lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPo
while (Sections.GetSize() < SynthInfo->NumSections + 2)
{
lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPoints.GetSize() - 1].Transform);
EndTransform = lcMul(EndTransform, lcMatrix44(lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, -1.0f, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f)));
EndTransform = lcMatrix44(lcMul(lcMatrix33(EndTransform), lcMatrix33(lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, -1.0f, 0.0f), lcVector3(0.0f, 0.0f, 1.0f))), EndTransform.GetTranslation());
lcVector3 Position = lcMul31(lcVector3(0.0f, SectionLength, 0.0f), EndTransform);
EndTransform.SetTranslation(Position);
Sections.Add(EndTransform);
if (SectionCallback)
SectionCallback(Position, ControlPoints.GetSize() - 1, 1.0f, CallbackParam);
if (Sections.GetSize() < SynthInfo->NumSections + 1)
SectionLength += SynthInfo->Components[1].Length;
else
SectionLength += SynthInfo->Components[2].Length;
}
}
lcMesh* lcSynthCreateMesh(const lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPoint>& ControlPoints)
{
lcArray<lcMatrix44> Sections;
lcSynthEvaluate(SynthInfo, ControlPoints, Sections, NULL, NULL);
// todo: rewrite this to pass the parts directly
@@ -224,3 +223,58 @@ lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPo
return NULL;
}
struct lcSynthInsertParam
{
lcVector3 Start;
lcVector3 End;
int BestSegment;
float BestTime;
float BestDistance;
lcVector3 BestPosition;
};
static void lcSynthInsertCallback(const lcVector3& CurvePoint, int SegmentIndex, float t, void* Param)
{
lcSynthInsertParam* SynthInsertParam = (lcSynthInsertParam*)Param;
float Distance = lcRayPointDistance(CurvePoint, SynthInsertParam->Start, SynthInsertParam->End);
if (Distance < SynthInsertParam->BestDistance)
{
SynthInsertParam->BestSegment = SegmentIndex;
SynthInsertParam->BestTime = t;
SynthInsertParam->BestDistance = Distance;
SynthInsertParam->BestPosition = lcVector3LDrawToLeoCAD(CurvePoint);
}
}
int lcSynthInsertControlPoint(const lcSynthInfo* SynthInfo, lcArray<lcPieceControlPoint>& ControlPoints, const lcVector3& Start, const lcVector3& End)
{
lcArray<lcMatrix44> Sections;
lcSynthInsertParam SynthInsertParam;
SynthInsertParam.Start = Start;
SynthInsertParam.End = End;
SynthInsertParam.BestSegment = -1;
SynthInsertParam.BestDistance = FLT_MAX;
lcSynthEvaluate(SynthInfo, ControlPoints, Sections, lcSynthInsertCallback, &SynthInsertParam);
if (SynthInsertParam.BestSegment != -1)
{
lcPieceControlPoint ControlPoint = ControlPoints[SynthInsertParam.BestSegment];
ControlPoint.Transform.SetTranslation(SynthInsertParam.BestPosition);
if (SynthInsertParam.BestSegment != ControlPoints.GetSize() - 1)
{
lcPieceControlPoint NextControlPoint = ControlPoints[SynthInsertParam.BestSegment + 1];
float t = SynthInsertParam.BestTime;
ControlPoint.Stiffness = ControlPoint.Stiffness * (1.0f - t) + NextControlPoint.Stiffness * t;
}
ControlPoints.InsertAt(SynthInsertParam.BestSegment + 1, ControlPoint);
}
return SynthInsertParam.BestSegment + 1;
}
+2 -1
View File
@@ -21,6 +21,7 @@ struct lcSynthInfo
};
void lcSynthInit();
lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPoint>& ControlPoints);
lcMesh* lcSynthCreateMesh(const lcSynthInfo* SynthInfo, const lcArray<lcPieceControlPoint>& ControlPoints);
int lcSynthInsertControlPoint(const lcSynthInfo* SynthInfo, lcArray<lcPieceControlPoint>& ControlPoints, const lcVector3& Start, const lcVector3& End);
#endif // _LC_SYNTH_H_
+37
View File
@@ -732,6 +732,43 @@ void lcPiece::RotatePivotPoint(const lcMatrix33& RotationMatrix)
mState |= LC_PIECE_PIVOT_POINT_VALID;
}
bool lcPiece::InsertControlPoint(const lcVector3& WorldStart, const lcVector3& WorldEnd)
{
if (!mPieceInfo->GetSynthInfo())
return false;
lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mModelWorld);
lcVector3 Start = lcMul31(WorldStart, InverseWorldMatrix);
lcVector3 End = lcMul31(WorldEnd, InverseWorldMatrix);
int ControlPointIndex = lcSynthInsertControlPoint(mPieceInfo->GetSynthInfo(), mControlPoints, Start, End);
if (ControlPointIndex)
{
SetFocused(GetFocusSection(), false);
SetFocused(LC_PIECE_SECTION_CONTROL_POINT_1 + ControlPointIndex, true);
UpdateMesh();
return true;
}
return false;
}
bool lcPiece::RemoveFocusedControlPoint()
{
int ControlPointIndex = GetFocusSection() - LC_PIECE_SECTION_CONTROL_POINT_1;
if (ControlPointIndex < 0 || ControlPointIndex >= mControlPoints.GetSize() || mControlPoints.GetSize() <= 2)
return false;
SetFocused(GetFocusSection(), false);
SetFocused(LC_PIECE_SECTION_POSITION, true);
mControlPoints.RemoveIndex(ControlPointIndex);
UpdateMesh();
return true;
}
const char* lcPiece::GetName() const
{
return mPieceInfo->m_strDescription;
+8
View File
@@ -361,6 +361,11 @@ public:
mState &= ~LC_PIECE_HIDDEN;
}
const lcArray<lcPieceControlPoint>& GetControlPoints() const
{
return mControlPoints;
}
const char* GetName() const;
bool IsVisible(lcStep Step);
void Initialize(const lcMatrix44& WorldMatrix, lcStep Step);
@@ -375,6 +380,9 @@ public:
void MovePivotPoint(const lcVector3& Distance);
void RotatePivotPoint(const lcMatrix33& RotationMatrix);
bool InsertControlPoint(const lcVector3& WorldStart, const lcVector3& WorldEnd);
bool RemoveFocusedControlPoint();
lcGroup* GetTopGroup();
void SetGroup(lcGroup* Group)
+19
View File
@@ -386,6 +386,11 @@ void View::ShowContextMenu() const
Popup->addSeparator();
Popup->addAction(Actions[LC_PIECE_CONTROL_POINT_INSERT]);
Popup->addAction(Actions[LC_PIECE_CONTROL_POINT_REMOVE]);
Popup->addSeparator();
Popup->addAction(Actions[LC_PIECE_VIEW_SELECTED_MODEL]);
Popup->addAction(Actions[LC_PIECE_INLINE_SELECTED_MODELS]);
Popup->addAction(Actions[LC_PIECE_MOVE_SELECTION_TO_MODEL]);
@@ -486,6 +491,20 @@ lcMatrix44 View::GetPieceInsertPosition() const
return lcMatrix44Translation(UnprojectPoint(lcVector3((float)mInputState.x, (float)mInputState.y, 0.9f)));
}
void View::GetRayUnderPointer(lcVector3& Start, lcVector3& End) const
{
lcVector3 StartEnd[2] =
{
lcVector3((float)mInputState.x, (float)mInputState.y, 0.0f),
lcVector3((float)mInputState.x, (float)mInputState.y, 1.0f)
};
UnprojectPoints(StartEnd, 2);
Start = StartEnd[0];
End = StartEnd[1];
}
lcObjectSection View::FindObjectUnderPointer(bool PiecesOnly) const
{
lcVector3 StartEnd[2] =
+1
View File
@@ -97,6 +97,7 @@ public:
lcVector3 GetMoveDirection(const lcVector3& Direction) const;
lcMatrix44 GetPieceInsertPosition() const;
void GetRayUnderPointer(lcVector3& Start, lcVector3& End) const;
lcObjectSection FindObjectUnderPointer(bool PiecesOnly) const;
lcArray<lcObject*> FindObjectsInBox(float x1, float y1, float x2, float y2) const;