fix(physics): prevent double-joining

This commit is contained in:
maelstrom 2025-04-23 15:15:58 +02:00
parent e35c895233
commit 587629fcdd
3 changed files with 30 additions and 7 deletions

View file

@ -259,6 +259,26 @@ SurfaceType Part::surfaceFromFace(NormalId face) {
return SurfaceSmooth; // Unreachable return SurfaceSmooth; // Unreachable
} }
bool Part::checkJointContinuinty(std::shared_ptr<Part> otherPart) {
// Make sure that the two parts don't depend on one another
if (shared<Part>() == otherPart) return false;
for (auto joint : primaryJoints) {
if (joint.expired() || joint.lock()->part1.expired()) continue;
if (!joint.lock()->part1.lock()->checkJointContinuinty(otherPart))
return false;
}
for (auto joint : secondaryJoints) {
if (joint.expired() || joint.lock()->part0.expired()) continue;
if (!joint.lock()->part0.lock()->checkJointContinuinty(otherPart))
return false;
}
return true;
}
void Part::MakeJoints() { void Part::MakeJoints() {
// Algorithm: Find nearby parts // Algorithm: Find nearby parts
// Make sure parts are not dependant on each other (via primary/secondaryJoints) // Make sure parts are not dependant on each other (via primary/secondaryJoints)
@ -290,6 +310,7 @@ void Part::MakeJoints() {
float dot = myWorldNormal.Dot(otherWorldNormal); float dot = myWorldNormal.Dot(otherWorldNormal);
if (dot > -0.99) continue; // Surface is pointing opposite to ours if (dot > -0.99) continue; // Surface is pointing opposite to ours
if (abs(surfacePointLocalToMyFrame.Z()) > 0.05) continue; // Surfaces are within 0.05 studs of one another if (abs(surfacePointLocalToMyFrame.Z()) > 0.05) continue; // Surfaces are within 0.05 studs of one another
if (!checkJointContinuinty(otherPart)) continue;
SurfaceType mySurface = surfaceFromFace(faceFromNormal(myFace)); SurfaceType mySurface = surfaceFromFace(faceFromNormal(myFace));
SurfaceType otherSurface = surfaceFromFace(faceFromNormal(otherFace)); SurfaceType otherSurface = surfaceFromFace(faceFromNormal(otherFace));
@ -307,7 +328,7 @@ void Part::MakeJoints() {
dataModel().value()->GetService<JointsService>()->AddChild(joint); dataModel().value()->GetService<JointsService>()->AddChild(joint);
joint->UpdateProperty("Part0"); joint->UpdateProperty("Part0");
printf("Made joint between %s and %s!\n", name.c_str(), otherPart->name.c_str()); Logger::debugf("Made joint between %s and %s!\n", name.c_str(), otherPart->name.c_str());
} }
} }
} }

View file

@ -37,6 +37,7 @@ protected:
void untrackJoint(std::shared_ptr<Snap>); void untrackJoint(std::shared_ptr<Snap>);
SurfaceType surfaceFromFace(NormalId); SurfaceType surfaceFromFace(NormalId);
bool checkJointContinuinty(std::shared_ptr<Part>);
friend Snap; friend Snap;

View file

@ -368,18 +368,18 @@ void MainWindow::connectActionHandlers() {
connect(ui->actionSave, &QAction::triggered, this, [&]() { connect(ui->actionSave, &QAction::triggered, this, [&]() {
std::optional<std::string> path; std::optional<std::string> path;
if (!gDataModel->HasFile()) if (!editModeDataModel->HasFile())
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + gDataModel->name)); path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + editModeDataModel->name));
if (!gDataModel->HasFile() && (!path || path == "")) return; if (!editModeDataModel->HasFile() && (!path || path == "")) return;
gDataModel->SaveToFile(path); editModeDataModel->SaveToFile(path);
}); });
connect(ui->actionSaveAs, &QAction::triggered, this, [&]() { connect(ui->actionSaveAs, &QAction::triggered, this, [&]() {
std::optional<std::string> path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save as " + gDataModel->name)); std::optional<std::string> path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save as " + editModeDataModel->name));
if (!path || path == "") return; if (!path || path == "") return;
gDataModel->SaveToFile(path); editModeDataModel->SaveToFile(path);
}); });
connect(ui->actionOpen, &QAction::triggered, this, [&]() { connect(ui->actionOpen, &QAction::triggered, this, [&]() {
@ -391,6 +391,7 @@ void MainWindow::connectActionHandlers() {
// simulationInit(); // simulationInit();
std::shared_ptr<DataModel> newModel = DataModel::LoadFromFile(path.value()); std::shared_ptr<DataModel> newModel = DataModel::LoadFromFile(path.value());
editModeDataModel = newModel;
gDataModel = newModel; gDataModel = newModel;
newModel->Init(); newModel->Init();
ui->explorerView->updateRoot(newModel); ui->explorerView->updateRoot(newModel);