PeriDyno 1.0.0
Loading...
Searching...
No Matches
PSimulationThread.cpp
Go to the documentation of this file.
1#include "PSimulationThread.h"
2
3#include <memory>
4#include <mutex>
5#include <utility>
6
7#include "Node.h"
8#include "SceneGraph.h"
9#include "SceneGraphFactory.h"
10
11#include "Action.h"
12
14
15using namespace std::chrono_literals;
16namespace dyno
17{
18 QWaitCondition m_wait_condition;
19
21 :
22 mTotalFrame(1000),
23 mReset(false),
24 mPaused(true),
25 mRunning(true),
26 mFinished(false),
28 mTimeOut(10000)
29 {
30 }
31
32 std::atomic<PSimulationThread*> PSimulationThread::pInstance;
34
36 {
37 PSimulationThread* ins = pInstance.load(std::memory_order_acquire);
38 if (!ins) {
39 std::lock_guard<std::mutex> tLock(mInstanceMutex);
40 ins = pInstance.load(std::memory_order_relaxed);
41 if (!ins) {
42 ins = new PSimulationThread();
43 pInstance.store(ins, std::memory_order_release);
44 }
45 }
46
47 return ins;
48 }
49
51 {
52 mPaused = true;
53 }
54
56 {
57 mPaused = false;
58 notify();
59 }
60
62 {
63 mRunning = false;
64 notify();
65 }
66
68 {
69 if (mMutex.try_lock_for(mTimeOut))
70 {
72 this->reset(0);
73
74 mMutex.unlock();
75
76 emit sceneGraphChanged();
77 }
78 else
79 {
80 Log::sendMessage(Log::Info, "Time out");
81 }
82 }
83
84
85 void PSimulationThread::createNewScene(std::shared_ptr<SceneGraph> scn)
86 {
87 if (mMutex.try_lock_for(mTimeOut))
88 {
90 scn->reset();
91 this->reset(0);
92
93 mMutex.unlock();
94
95 emit sceneGraphChanged();
96 }
97 else
98 {
99 Log::sendMessage(Log::Info, "Time out");
100 }
101 }
102
104 {
105 if (mMutex.try_lock_for(mTimeOut))
106 {
108 this->reset(0);
109
110 mMutex.unlock();
111
112 emit sceneGraphChanged();
113 }
114 else
115 {
116 Log::sendMessage(Log::Info, "Time out");
117 }
118 }
119
121 {
122 if (mMutex.try_lock_for(mTimeOut))
123 {
125 this->reset(0);
126
127 mMutex.unlock();
128
129 emit sceneGraphChanged();
130 }
131 else
132 {
133 Log::sendMessage(Log::Info, "Time out");
134 }
135 }
136
138 mCond.notify_one();
139 }
140
142 {
143 for(;;)
144 {
145 std::unique_lock<decltype(mMutex)> lock(mMutex);
146 auto scn = SceneGraphFactory::instance()->active();
147
148 bool has_frame = scn->getFrameNumber() < mTotalFrame;
149
150 while(mRunning && (mUpdatingGraphicsContext || (!mReset && mPaused))) {
151 mCond.wait_for(lock, 500ms);
152 }
153
154 if(!mRunning) break;
155
156 if (mReset)
157 {
158 if (mActiveNode == nullptr) {
159 scn->reset();
160
161 mFinished = false;
162 }
163 else {
164 scn->reset(mActiveNode);
165
166 mActiveNode = nullptr;
167 }
168
169 mReset = false;
170
171 emit oneFrameFinished(scn->getFrameNumber());
172 }
173
174 if(!mPaused) {
175 if (scn->getFrameNumber() < mTotalFrame)
176 {
177 scn->takeOneFrame();
178
180
181 if (mOneStep) {
182 mOneStep = false;
183 mPaused = true;
184 }
185
186 emit oneFrameFinished(scn->getFrameNumber());
187 }
188
189 if (scn->getFrameNumber() >= mTotalFrame)
190 {
191 mPaused = true;
192 if(!std::exchange(mFinished,true)) {
193 emit simulationFinished();
194 }
195 }
196 }
197 }
198 }
199
201 {
202 this->pause();
203
204 mFinished = true;
205
206 mTotalFrame = num;
207
208 mActiveNode = nullptr;
209
210 auto scn = SceneGraphFactory::instance()->active();
211 scn->setFrameNumber(0);
212
213 //Note: should set mReset at the end
214 mReset = true;
215 notify();
216 }
217
219 {
220 this->pause();
221
222 mFinished = false;
223
224 mTotalFrame = num;
225
226 notify();
227 }
228
229 void PSimulationThread::resetNode(std::shared_ptr<Node> node)
230 {
231 auto scn = SceneGraphFactory::instance()->active();
232 scn->reset(node);
233
234 notify();
235 }
236
237 void PSimulationThread::resetQtNode(Qt::QtNode& node)
238 {
239 auto model = node.nodeDataModel();
240 auto widget = dynamic_cast<Qt::QtNodeWidget*>(model);
241
242 if (widget != nullptr)
243 {
244 mActiveNode = widget->getNode();
245 mReset = true;
246 }
247 }
248
249 void PSimulationThread::syncNode(std::shared_ptr<Node> node)
250 {
251 auto scn = SceneGraphFactory::instance()->active();
252
253 class SyncNodeAct : public Action
254 {
255 public:
256 void process(Node* node) override {
257 node->reset();
258 node->updateGraphicsContext();
259 }
260 };
261
262 scn->traverseForwardWithAutoSync<SyncNodeAct>(node);
263
264 notify();
265 }
266
271
277
279 {
280 mTotalFrame = num;
281 notify();
282 }
283
285 {
286 mPaused = false;
287 mOneStep = true;
288 notify();
289 }
290
292 {
293 auto scn = SceneGraphFactory::instance()->active();
294 return scn->getFrameNumber();
295 }
296}
The model dictates the number of inputs and outputs for the Node.
@ Info
Information to user.
Definition Log.h:48
static void sendMessage(MessageType type, const std::string &text)
Add a new message to log.
Definition Log.cpp:41
void updateGraphicsContext()
Definition Node.cpp:206
void reset()
Definition Node.cpp:183
static std::atomic< PSimulationThread * > pInstance
void reset(int num)
Reset the simulation.
std::atomic< bool > mPaused
void oneFrameFinished(int frame)
std::shared_ptr< Node > mActiveNode
std::atomic< bool > mUpdatingGraphicsContext
std::condition_variable_any mCond
static PSimulationThread * instance()
void syncNode(std::shared_ptr< Node > node)
void resetQtNode(Qt::QtNode &node)
std::chrono::milliseconds mTimeOut
std::atomic< bool > mRunning
void proceed(int num)
Continue the simulation from the current frame.
void resetNode(std::shared_ptr< Node > node)
static std::mutex mInstanceMutex
std::atomic< int > mTotalFrame
std::shared_ptr< SceneGraph > createNewScene()
Create a new SceneGraph.
static SceneGraphFactory * instance()
void pushScene(std::shared_ptr< SceneGraph > scn)
std::shared_ptr< SceneGraph > active()
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
QWaitCondition m_wait_condition