Physics Simulation & Visualization Tool 0.1
A C++ physics simulation engine with real-time 3D visualization
Loading...
Searching...
No Matches
GlobalsInspectorWidget.cpp
Go to the documentation of this file.
2#include <QFormLayout>
3#include <QPushButton>
4#include <QComboBox>
5#include <QStackedWidget>
6#include <QLabel>
7#include <QGroupBox>
8
11#include "physics/Constants.h"
13#include "ui/ScalarWidget.h"
14#include "ui/Vector3Widget.h"
15
16GlobalsInspectorWidget::GlobalsInspectorWidget(SceneManager* mgr, QWidget* parent) : IInspectorSection(parent), sceneManager(mgr) {
17 layout = new QFormLayout(this);
18 layout->setContentsMargins(6, 6, 6, 6);
19 layout->setSpacing(4);
20 setLayout(layout);
21
22 createUiComponents();
23}
24
25void GlobalsInspectorWidget::createUiComponents() {
26 {
27 InspectorRow row("Gravity", this);
28 row.addVec3(
29 [this]() { return sceneManager->getGlobalAcceleration(); },
30 [this](glm::vec3 g) { sceneManager->setGlobalAcceleration(g); },
31 "m/s²"
32 );
33 layout->addRow(row.getLabel(), row.getEditor());
34 rows.push_back(std::move(row));
35 }
36
37 {
38 InspectorRow row("Gravitational Constant", this);
39 Physics::PhysicsSystem* physicSystem = sceneManager->physicsSystem.get();
40 row.addScalar(
41 [physicSystem]() { return physicSystem->getGravitationalConstant(); },
42 [physicSystem](double g) { physicSystem->setGravitationalConstant(g); },
43 "N·m²/kg²",
44 [](ScalarWidget* widget) {
45 widget->setDecimals(15);
46 }
47 ).addButton("Default scaled", [this, physicSystem]() {
49 refresh();
50 }).addButton("Realism (reset)", [this, physicSystem]() {
52 refresh();
53 });
54 layout->addRow(row.getLabel(), row.getEditor());
55 rows.push_back(std::move(row));
56 }
57
58 {
59 InspectorRow row("Sim Speed", this);
60 row.addScalar(
61 [this]() { return sceneManager->getSimSpeed(); },
62 [this](float s) { sceneManager->setSimSpeed(s); },
63 "x",
64 [](ScalarWidget* widget) {
65 widget->setRange(0.0, 1.0e12);
66 }
67 );
68 layout->addRow(row.getLabel(), row.getEditor());
69 rows.push_back(std::move(row));
70 }
71
72 {
73 InspectorRow row("Ambient Temp", this);
74 Physics::PhysicsSystem* physicSystem = sceneManager->physicsSystem.get();
75 row.addScalar(
76 [physicSystem]() { return physicSystem->getAmbientTemperature(); },
77 [physicSystem](float t) { physicSystem->setAmbientTemperature(t); },
78 "K"
79 ).addButton("Room Temp", [this, physicSystem]() {
80 physicSystem->setAmbientTemperature(293.15f);
81 refresh();
82 });
83 layout->addRow(row.getLabel(), row.getEditor());
84 rows.push_back(std::move(row));
85 }
86
87 createStopConditionUi();
88
89 // {
90 // timeConstraint = new ScalarWidget(" s");
91 // timeConstraint->setValue(0.0);
92 //
93 // InspectorRow row("Flight Time", timeConstraint, nullptr);
94 // layout->addRow(row.getLabel(), row.getEditor());
95 // rows.push_back(std::move(row));
96 // }
97
98 {
99 QPushButton* solveBtn = new QPushButton("SOLVE PHYSICS");
100 solveBtn->setFixedHeight(30);
101
102 connect(solveBtn, &QPushButton::clicked, this, &GlobalsInspectorWidget::runSolver);
103
104 InspectorRow row("", solveBtn, nullptr);
105 layout->addRow(row.getLabel(), row.getEditor());
106 rows.push_back(std::move(row));
107 }
108}
109
110void GlobalsInspectorWidget::createStopConditionUi() {
111 QWidget* logicContainer = new QWidget();
112 logicContainer->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
113 QVBoxLayout* mainContainerLayout = new QVBoxLayout(logicContainer);
114 mainContainerLayout->setContentsMargins(0, 0, 0, 0);
115 mainContainerLayout->setSpacing(2);
116
117 QWidget* equationRow = new QWidget();
118 QHBoxLayout* equationLayout = new QHBoxLayout(equationRow);
119 equationLayout->setContentsMargins(0, 0, 0, 0);
120
121 QComboBox* subjectCombo = new QComboBox();
122 QComboBox* propCombo = new QComboBox();
123 QComboBox* opCombo = new QComboBox();
124 ScalarWidget* thresholdWidget = new ScalarWidget(" m");
125
126 QStackedWidget* parameterStack = new QStackedWidget();
127 parameterStack->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
128
129 QWidget* emptyPage = new QWidget();
130 emptyPage->setFixedHeight(0);
131 parameterStack->addWidget(emptyPage);
132
133 QComboBox* targetObjCombo = new QComboBox();
134 parameterStack->addWidget(targetObjCombo);
135
136 Vector3Widget* targetVecWidget = new Vector3Widget();
137 parameterStack->addWidget(targetVecWidget);
138
139 subjectCombo->addItem("-- Subject --", -1);
140 for (const auto& objPtr : sceneManager->getObjects()) {
141 SceneObject* obj = objPtr.get();
142 subjectCombo->addItem(QString::fromStdString(obj->getName()), obj->getObjectID());
143 }
144 connect(subjectCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, subjectCombo](int){
145 sceneManager->stopCondition.subjectID = subjectCombo->currentData().toInt();
146 refresh();
147 });
148
149 propCombo->addItem("Pos Y", 0);
150 propCombo->addItem("Vel Y", 1);
151 propCombo->addItem("Dist to Obj", 2);
152 propCombo->addItem("Dist to Point", 3);
153 connect(propCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int idx){
154 sceneManager->stopCondition.property = idx;
155 refresh();
156 });
157
158 opCombo->addItem("<", 0);
159 opCombo->addItem(">", 1);
160 connect(opCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int idx){
161 sceneManager->stopCondition.op = idx;
162 });
163
164 connect(thresholdWidget, &ScalarWidget::valueChanged, [this](double v){
165 sceneManager->stopCondition.value = (float)v;
166 });
167
168 connect(targetObjCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, targetObjCombo](int){
169 sceneManager->stopCondition.targetID = targetObjCombo->currentData().toInt();
170 });
171
172 connect(targetVecWidget, &Vector3Widget::valueChanged, [this](glm::vec3 v){
173 sceneManager->stopCondition.targetPos = v;
174 });
175
176 equationLayout->addWidget(subjectCombo);
177 equationLayout->addWidget(propCombo);
178 equationLayout->addWidget(opCombo);
179 equationLayout->addWidget(thresholdWidget);
180
181 mainContainerLayout->addWidget(equationRow);
182 mainContainerLayout->addWidget(parameterStack);
183
184 auto updateLogic = [this, subjectCombo, propCombo, opCombo, thresholdWidget, parameterStack, targetObjCombo, targetVecWidget]() {
185 int subjIdx = subjectCombo->findData(sceneManager->stopCondition.subjectID);
186 const QSignalBlocker b1(subjectCombo);
187 subjectCombo->setCurrentIndex(subjIdx != -1 ? subjIdx : 0);
188
189 if (subjectCombo->count() != sceneManager->getObjects().size() + 1) {
190 subjectCombo->clear();
191 subjectCombo->addItem("-- Subject --", -1);
192 for (const auto& objPtr : sceneManager->getObjects()) {
193 SceneObject* obj = objPtr.get();
194 subjectCombo->addItem(QString::fromStdString(obj->getName()), obj->getObjectID());
195 }
196 subjIdx = subjectCombo->findData(sceneManager->stopCondition.subjectID);
197 subjectCombo->setCurrentIndex(subjIdx != -1 ? subjIdx : 0);
198 }
199
200 const QSignalBlocker b2(propCombo);
201 propCombo->setCurrentIndex(sceneManager->stopCondition.property);
202
203 const QSignalBlocker b3(opCombo);
204 opCombo->setCurrentIndex(sceneManager->stopCondition.op);
205
206 const QSignalBlocker b4(thresholdWidget);
207 thresholdWidget->setValue(sceneManager->stopCondition.value);
208
209 int prop = sceneManager->stopCondition.property;
210 if (prop == 2) { // Dist to Obj
211 parameterStack->setCurrentIndex(1);
212 parameterStack->setVisible(true);
213
214 if (targetObjCombo->count() != sceneManager->getObjects().size()) {
215 const QSignalBlocker b(targetObjCombo);
216 targetObjCombo->clear();
217 for (const auto& objPtr : sceneManager->getObjects()) {
218 SceneObject* obj = objPtr.get();
219 targetObjCombo->addItem(QString::fromStdString(obj->getName()), obj->getObjectID());
220 }
221 }
222
223 int tIdx = targetObjCombo->findData(sceneManager->stopCondition.targetID);
224 if (tIdx != -1 && targetObjCombo->currentIndex() != tIdx) {
225 const QSignalBlocker b(targetObjCombo);
226 targetObjCombo->setCurrentIndex(tIdx);
227 }
228 }
229 else if (prop == 3) { // Dist to Point
230 parameterStack->setCurrentIndex(2);
231 parameterStack->setVisible(true);
232
233 const QSignalBlocker b5(targetVecWidget);
234 targetVecWidget->setValue(sceneManager->stopCondition.targetPos);
235 }
236 else {
237 parameterStack->setCurrentIndex(0);
238 parameterStack->setVisible(false);
239 }
240
241 bool active = (sceneManager->stopCondition.subjectID != -1);
242 propCombo->setEnabled(active);
243 opCombo->setEnabled(active);
244 thresholdWidget->setEnabled(active);
245 parameterStack->setEnabled(active);
246 };
247
248 updateLogic();
249
250 InspectorRow row("Stop Condition", logicContainer, updateLogic);
251 layout->addRow(row.getLabel(), row.getEditor());
252 rows.push_back(std::move(row));
253}
254
256 setVisible(true);
257 refresh();
258}
259
261 // Globals persist
262}
263
265 for (auto& row : rows)
266 row.refresh();
267}
268
270 auto& cond = sceneManager->stopCondition;
271 if (cond.subjectID == -1) return;
272
273 Physics::PhysicsBody* body = sceneManager->physicsSystem->getBodyById(cond.subjectID);
274 if (!body) return;
275
276 std::unordered_map<std::string, double> knowns;
277
278 if (!body->isUnknown("r0", BodyLock::LOCK)) {
279 glm::vec3 r0 = body->getPosition(BodyLock::LOCK);
280 knowns["r0_x"] = r0.x;
281 knowns["r0_y"] = r0.y;
282 knowns["r0_z"] = r0.z;
283 }
284
285 if (!body->isUnknown("v0", BodyLock::LOCK)) {
286 glm::vec3 v0 = body->getVelocity(BodyLock::LOCK);
287 knowns["v0_x"] = v0.x;
288 knowns["v0_y"] = v0.y;
289 knowns["v0_z"] = v0.z;
290 }
291
292 knowns["Stop_SubjectID"] = (double)cond.subjectID;
293 knowns["Stop_Prop"] = (double)cond.property;
294 knowns["Stop_Op"] = (double)cond.op;
295 knowns["Stop_Val"] = (double)cond.value;
296 knowns["Stop_TargetID"] = (double)cond.targetID;
297
298 knowns["Stop_Val_X"] = cond.targetPos.x;
299 knowns["Stop_Val_Y"] = cond.targetPos.y;
300 knowns["Stop_Val_Z"] = cond.targetPos.z;
301
302 bool isInverse = body->isUnknown("v0", BodyLock::NOLOCK) || body->isUnknown("r0", BodyLock::NOLOCK);
303
304 std::string unknownKey = "Event";
305 if (body->isUnknown("v0", BodyLock::LOCK)) {
306 unknownKey = "v0";
307 }
308 else if (body->isUnknown("r0", BodyLock::LOCK)) {
309 unknownKey = "r0";
310 }
311
312 double targetTime = -1.0;
313 if (timeConstraint) {
314 targetTime = timeConstraint->getValue();
315 if (targetTime <= 0.0001) targetTime = -1.0;
316 }
317 knowns["Target_Time"] = targetTime;
318
319 SceneObject* visualSubject = nullptr;
320 for (const auto& objPtr : sceneManager->getObjects()) {
321 SceneObject* obj = objPtr.get();
322 if (static_cast<int>(obj->getObjectID()) == cond.subjectID) {
323 visualSubject = obj;
324 break;
325 }
326 }
327
328 if (visualSubject) {
329 sceneManager->setCameraTarget(visualSubject);
330 }
331
332 sceneManager->physicsSystem->solveProblem(body, knowns, unknownKey);
333 emit solveRequested();
334 refresh();
335}
void load(SceneObject *object) override
Loads and binds this section to a scene object.
void refresh() override
Updates UI widgets from the current object's state.
GlobalsInspectorWidget(SceneManager *mgr, QWidget *parent=nullptr)
void unload() override
Unloads the current object and clears section state.
Abstract base class for inspector panel sections.
bool isUnknown(const std::string &key, BodyLock lock) const
glm::vec3 getVelocity(BodyLock lock) const
glm::vec3 getPosition(BodyLock lock) const
void setAmbientTemperature(float newTemp)
float getAmbientTemperature() const
void setGravitationalConstant(double newG)
double getGravitationalConstant() const
void valueChanged(double newValue)
double getValue() const
void setSimSpeed(float newSpeed)
void setGlobalAcceleration(const glm::vec3 &newAcceleration) const
std::unique_ptr< Physics::PhysicsSystem > physicsSystem
SimulationStopCondition stopCondition
void setCameraTarget(SceneObject *target)
glm::vec3 getGlobalAcceleration() const
float getSimSpeed() const
const std::vector< std::unique_ptr< SceneObject > > & getObjects() const
const std::string & getName() const
Definition SceneObject.h:48
uint32_t getObjectID() const override
Gets the unique identifier for this object.
void valueChanged(const glm::vec3 &newValue)
void setValue(const glm::vec3 &v)
constexpr double G_SCALED
Definition Constants.h:4
constexpr double G
Definition Constants.h:5