Detect train track connections and pick an open one when inserting.

This commit is contained in:
Leonardo Zide 2024-11-27 13:04:53 -08:00
parent f80b5c95e1
commit a08ad3f81b
7 changed files with 117 additions and 25 deletions

View file

@ -1316,10 +1316,15 @@ void lcModel::GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHig
if (mPieceInfo)
mPieceInfo->AddRenderMesh(*Scene);
lcPiece* FocusPiece = nullptr;
for (const std::unique_ptr<lcPiece>& Piece : mPieces)
{
if (Piece->IsVisible(mCurrentStep))
{
if (Piece->IsFocused())
FocusPiece = Piece.get();
const lcStep StepShow = Piece->GetStepShow();
Piece->AddMainModelRenderMeshes(Scene, AllowHighlight && StepShow == mCurrentStep, AllowFade && StepShow < mCurrentStep);
}
@ -1327,6 +1332,9 @@ void lcModel::GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHig
if (Scene->GetDrawInterface() && !Scene->GetActiveSubmodelInstance())
{
if (FocusPiece)
UpdateTrainTrackConnections(FocusPiece);
for (const std::unique_ptr<lcCamera>& Camera : mCameras)
if (Camera.get() != ViewCamera && Camera->IsVisible())
Scene->AddInterfaceObject(Camera.get());
@ -2356,6 +2364,32 @@ void lcModel::InsertPiece(lcPiece* Piece, size_t Index)
mPieces.insert(mPieces.begin() + Index, std::unique_ptr<lcPiece>(Piece));
}
void lcModel::UpdateTrainTrackConnections(lcPiece* FocusPiece) const
{
if (!FocusPiece || !FocusPiece->IsFocused())
return;
const lcTrainTrackInfo* TrainTrackInfo = FocusPiece->mPieceInfo->GetTrainTrackInfo();
if (!TrainTrackInfo)
return;
const int ConnectionCount = static_cast<int>(TrainTrackInfo->GetConnections().size());
std::vector<bool> Connections(ConnectionCount, false);
for (const std::unique_ptr<lcPiece>& Piece : mPieces)
{
if (Piece.get() == FocusPiece || !Piece->mPieceInfo->GetTrainTrackInfo())
continue;
for (int ConnectionIndex = 0; ConnectionIndex < ConnectionCount; ConnectionIndex++)
if (!Connections[ConnectionIndex] && lcTrainTrackInfo::ArePiecesConnected(FocusPiece, ConnectionIndex, Piece.get()))
Connections[ConnectionIndex] = true;
}
FocusPiece->SetTrainTrackConnections(std::move(Connections));
}
void lcModel::DeleteAllCameras()
{
if (mCameras.empty())
@ -3782,11 +3816,13 @@ void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool
if (Object->IsPiece())
{
SelectGroup(((lcPiece*)Object)->GetTopGroup(), true);
lcPiece* Piece = dynamic_cast<lcPiece*>(Object);
SelectGroup(Piece->GetTopGroup(), true);
if (EnableSelectionMode)
{
std::vector<lcObject*> Pieces = GetSelectionModePieces((lcPiece*)Object);
std::vector<lcObject*> Pieces = GetSelectionModePieces(Piece);
AddToSelection(Pieces, false, false);
}
}

View file

@ -390,6 +390,8 @@ protected:
void AddPiece(lcPiece* Piece);
void InsertPiece(lcPiece* Piece, size_t Index);
void UpdateTrainTrackConnections(lcPiece* FocusPiece) const;
lcPOVRayOptions mPOVRayOptions;
lcModelProperties mProperties;
Project* const mProject;

View file

@ -111,6 +111,29 @@ std::pair<PieceInfo*, lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPi
return { Info, Transform };
}
bool lcTrainTrackInfo::ArePiecesConnected(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2)
{
const lcTrainTrackInfo* TrainTrackInfo1 = Piece1->mPieceInfo->GetTrainTrackInfo();
const lcTrainTrackInfo* TrainTrackInfo2 = Piece2->mPieceInfo->GetTrainTrackInfo();
lcMatrix44 Transform1 = lcMul(TrainTrackInfo1->GetConnections()[ConnectionIndex1].Transform, Piece1->mModelWorld);
for (const lcTrainTrackConnection& Connection2 : TrainTrackInfo2->GetConnections())
{
lcMatrix44 Transform2 = lcMul(Connection2.Transform, Piece2->mModelWorld);
if (lcLengthSquared(Transform1.GetTranslation() - Transform2.GetTranslation()) > 0.1f)
continue;
float Dot = lcDot3(Transform1[0], Transform2[0]);
if (Dot < -0.99f && Dot > -1.01f)
return true;
}
return false;
}
std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info)
{
if (!CurrentPiece || !Info)
@ -126,7 +149,9 @@ std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur
if (FocusSection == LC_PIECE_SECTION_POSITION || FocusSection == LC_PIECE_SECTION_INVALID)
{
// todo: search model for open connection
for (ConnectionIndex = 0; ConnectionIndex < CurrentTrackInfo->GetConnections().size(); ConnectionIndex++)
if (CurrentPiece->IsTrainTrackConnectionVisible(ConnectionIndex))
break;
}
else
{
@ -134,11 +159,11 @@ std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur
return std::nullopt;
ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
if (ConnectionIndex >= CurrentTrackInfo->GetConnections().size())
return std::nullopt;
}
if (ConnectionIndex >= CurrentTrackInfo->GetConnections().size())
return std::nullopt;
lcTrainTrackInfo* NewTrackInfo = Info->GetTrainTrackInfo();
if (!NewTrackInfo || NewTrackInfo->mConnections.empty())

View file

@ -27,6 +27,7 @@ public:
std::pair<PieceInfo*, lcMatrix44> GetPieceInsertTransform(lcPiece* Piece, quint32 ConnectionIndex, lcTrainTrackType TrainTrackType) const;
static std::optional<lcMatrix44> GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info);
static bool ArePiecesConnected(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2);
void AddConnection(const lcTrainTrackConnection& TrainTrackConnection)
{

View file

@ -371,26 +371,32 @@ void lcViewManipulator::DrawSelectMove(lcTrackButton TrackButton, lcTrackTool Tr
void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, float OverlayScale)
{
const lcTrainTrackInfo* TrainTrackInfo = Piece->mPieceInfo->GetTrainTrackInfo();
const std::vector<lcTrainTrackConnection>& Connections = TrainTrackInfo->GetConnections();
for (const lcTrainTrackConnection& TrainTrackConnection : TrainTrackInfo->GetConnections())
for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++)
{
if (!Piece->IsTrainTrackConnectionVisible(ConnectionIndex))
continue;
const lcMatrix44& Transform = Connections[ConnectionIndex].Transform;
lcVector3 Verts[static_cast<int>(lcTrainTrackType::Count) * 2];
int NumVerts = 0;
Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcVector3(TrainTrackConnection.Transform[0]) * 100) / OverlayScale;
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (Transform.GetTranslation() + lcVector3(Transform[0]) * 100) / OverlayScale;
Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / OverlayScale;
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / OverlayScale;
Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / OverlayScale;
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / OverlayScale;
Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / OverlayScale;
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / OverlayScale;
Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / OverlayScale;
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / OverlayScale;
Context->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
@ -956,17 +962,22 @@ std::pair<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove()
if (TrainTrackInfo)
{
for (quint32 Section = 0; Section < TrainTrackInfo->GetConnections().size(); Section++)
const std::vector<lcTrainTrackConnection>& Connections = TrainTrackInfo->GetConnections();
for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++)
{
const lcTrainTrackConnection& TrainTrackConnection = TrainTrackInfo->GetConnections()[Section];
if (!Piece->IsTrainTrackConnectionVisible(ConnectionIndex))
continue;
const lcMatrix44& Transform = Connections[ConnectionIndex].Transform;
lcVector3 Verts[static_cast<int>(lcTrainTrackType::Count)];
int NumVerts = 0;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcVector3(TrainTrackConnection.Transform[0]) * 100) / 1;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / 1;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / 1;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / 1;
Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / 1;
Verts[NumVerts++] = (Transform.GetTranslation() + lcVector3(Transform[0]) * 100) / 1;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / 1;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / 1;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / 1;
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / 1;
for (int VertexIndex = 0; VertexIndex < NumVerts; VertexIndex++)
{
@ -981,7 +992,7 @@ std::pair<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove()
NewTrackTool = lcTrackTool::Insert;
ClosestIntersectionDistance = IntersectionDistance;
NewTrackSection = Section | (VertexIndex << 8);
NewTrackSection = ConnectionIndex | (VertexIndex << 8);
}
}
}

View file

@ -520,6 +520,9 @@ void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const
for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++)
{
if (mTrainTrackConnections[ConnectionIndex])
continue;
const lcMatrix44 InverseTransform = lcMatrix44AffineInverse(Connections[ConnectionIndex].Transform);
const lcVector3 PointStart = lcMul31(Start, InverseTransform);
const lcVector3 PointEnd = lcMul31(End, InverseTransform);
@ -728,6 +731,9 @@ void lcPiece::DrawTrainTrackInterface(lcContext* Context, const lcMatrix44& Worl
for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++)
{
if (mTrainTrackConnections[ConnectionIndex])
continue;
Context->SetWorldMatrix(lcMul(Connections[ConnectionIndex].Transform, WorldMatrix));
Context->SetVertexBufferPointer(Verts);

View file

@ -150,6 +150,16 @@ public:
UpdateMesh();
}
bool IsTrainTrackConnectionVisible(int ConnectionIndex) const
{
return !mTrainTrackConnections[ConnectionIndex];
}
void SetTrainTrackConnections(std::vector<bool>&& Connections)
{
mTrainTrackConnections = std::move(Connections);
}
const QString& GetID() const
{
return mID;
@ -367,5 +377,6 @@ protected:
bool mSelected = false;
quint32 mFocusedSection = LC_PIECE_SECTION_INVALID;
std::vector<lcPieceControlPoint> mControlPoints;
std::vector<bool> mTrainTrackConnections;
lcMesh* mMesh = nullptr;
};