void SimState::run() { double simStartTime; double simCurrentTime; double timeDif; double previousFrameStart = glfwGetTime(); double deltaT; while (!shouldStopStateLoop) { simStartTime = glfwGetTime(); deltaT = simStartTime - previousFrameStart; updateSim(deltaT); //main thread only glfwPollEvents(); keyOps(); //clamp rate simCurrentTime = glfwGetTime(); timeDif = simCurrentTime - simStartTime; if (SIM_TIME > timeDif) { std::chrono::milliseconds duration((int)((SIM_TIME - timeDif) * 1000)); std::this_thread::sleep_for(duration); } previousFrameStart = simStartTime; updateUpdateThreadState(); //std::cout << "sim step" << std::endl; //pausing if (shouldPause) { //wait for the second thread to signal that it has completed a step and is pausing std::unique_lock<std::mutex> l(secondThreadDoneLock); secondShouldPause = true; while (!secondThreadDone) { secondThreadIsDone.wait(l); } glfwMakeContextCurrent(window); nonifyKeys(); //std::cout << "pausing done" << std::endl; } } }
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), d_numViewPorts(0) { d_qSimTimer = new QTimer(this); connect(d_qSimTimer, SIGNAL(timeout()), this, SLOT(updateSim())); d_qDrawTimer = new QTimer(this); connect(d_qDrawTimer, SIGNAL(timeout()), this, SLOT(drawViewPorts())); d_qDrawTimer->start(30); QDockWidget *dock = new QDockWidget("Simulation Commands", this); QGridLayout *mainLayout = new QGridLayout; mainLayout->setSizeConstraint(QLayout::SetFixedSize); // Create the simulation control buttons Button *startButton = createButton(tr("Start"), SLOT(startSim())); Button *stopButton = createButton(tr("Stop"), SLOT(stopSim())); Button *initButton = createButton(tr("Initialize"), SLOT(initializeSim())); QGroupBox *controlGroupBox = new QGroupBox(tr("Simulation Control")); QVBoxLayout *vControlBox = new QVBoxLayout; vControlBox->addWidget(startButton); vControlBox->addWidget(stopButton); vControlBox->addWidget(initButton); vControlBox->addStretch(1); controlGroupBox->setLayout(vControlBox); mainLayout->addWidget(controlGroupBox, 0, 0); // Add other buttons here // Add the mainlayout to the dock widget QWidget *wi = new QWidget; wi->setLayout(mainLayout); dock->setWidget(wi); addDockWidget(Qt::LeftDockWidgetArea, dock); setWindowTitle("Cloth Simulation"); d_cloth = new C_Cloth(); d_cloth->initialize(10.0f, 10.0f, 30, 30, 200, 550.0, 400.0, 0.005, ZAXIS); d_cloth->lockParticle(0, 0); d_cloth->lockParticle(0, 19); d_cloth->setGravity(vector3f(0.0, -32.0, 0)); }
void CcustomSim::beforeEnd(double newTime) { updateSim(newTime); }
void CcustomSim::beforeMiddle(double newTime) { updateSim(newTime); }
/******************************************************************* Submits all relevant run information to the run table *******************************************************************/ bool commitSimulation( Simulation* s ) { // do nothing if database is not configured if( DB::connectionInfo.dbname == "" ){ return true; } // set up thread-dependent db connection QSqlDatabase* db; dbLock.lock(); if( !dbStore.contains(QThread::currentThreadId()) ){ db = new QSqlDatabase(); *db = QSqlDatabase::addDatabase("QMYSQL", QString::number(QThread::currentThreadId())); db->setHostName(DB::connectionInfo.host); db->setDatabaseName(DB::connectionInfo.dbname); db->setUserName(DB::connectionInfo.user); db->setPassword(DB::connectionInfo.password); dbStore.insert(QThread::currentThreadId(), db); // make sure the database exists and the credentials are good if( !db->open() ){ qCritical() << "Could not open database"; return false; } } else { db = dbStore[QThread::currentThreadId()]; } dbLock.unlock(); // prepare queries QSqlQuery testState(*db), addState(*db), addSim(*db), updateSim(*db); QSqlQuery addLoop(*db), incrementLoop(*db), termLoopFromState(*db); testState.prepare( "SELECT COUNT(state_def) AS count, loop_id, sim_id FROM states " "WHERE state_def=:id;"); addState.prepare( "INSERT INTO states (state_def, next_state, stepnum, sim_id, loop_id) " "VALUES (:statedef, :nextstate, :stepnum, :simid, :loopid);"); addSim.prepare( "INSERT INTO simulations (sim_id, length) VALUES (:simid, :length);"); updateSim.prepare( "UPDATE simulations SET final_state=:final, term_loop_id=:termloopid " "WHERE sim_id=:id;"); addLoop.prepare( "INSERT INTO loops (loop_id, length, instance_cnt) " "VALUES (:loopid, :length, 0);"); incrementLoop.prepare( "UPDATE loops SET instance_cnt=instance_cnt+1 WHERE loop_id=:id;"); termLoopFromState.prepare( "SELECT simulations.term_loop_id AS termloop FROM states JOIN simulations " "ON states.sim_id=simulations.sim_id WHERE states.state_def=:id;"); State* i; State* initial = s->getInitialState(); ull loopState = 0; bool loopFlag = false; // make sure the simulation has been run if( initial == NULL || initial->next == NULL ){ qCritical() << "Cannot commit an incomplete simulation."; return false; } // lock simulation //QMutexLocker locker( &DB::simLock ); // start transaction db->transaction(); // loop over states for( i = initial; i!=NULL; i = i->next ) { // check if current state is in the db testState.bindValue( ":id", QVariant(i->pack()) ); if( !testState.exec() ){ qCritical() << "Cannot query state table!" << endl << testState.lastError().text(); db->rollback(); return false; } testState.first(); // if state IS NOT in db if( testState.record().value("count").toInt() == 0 ) { // initial state is fresh if( i == initial ) { // commit new simulation entry addSim.bindValue(":simid", QVariant(initial->pack())); addSim.bindValue(":length", QVariant(s->getTotalLength())); if( !addSim.exec() ){ qCritical() << "Cannot add new simulation to database!" << endl << addSim.lastError().text(); db->rollback(); return false; } } // state is the start of the loop if( *i == *(s->getLoopState()) ) { // set the loop id flag for future commits loopFlag = true; loopState = i->pack(); // create new entry in the loop table addLoop.bindValue(":id", QVariant(loopState)); addLoop.bindValue(":length", QVariant(s->getLoopLength())); if( !addLoop.exec() ){ qCritical() << "Cannot add new loop to database!" << endl << addLoop.lastError().text(); db->rollback(); return false; } } // commit state to db addState.bindValue(":statedef", QVariant(i->pack())); addState.bindValue(":nextstate", QVariant(i->next->pack())); addState.bindValue(":stepnum", QVariant(i->stepNum)); addState.bindValue(":simid", QVariant(initial->pack())); addState.bindValue(":loopid", loopFlag ? QVariant(loopState) : QVariant() ); if( !addState.exec() ){ qCritical() << "Cannot add new state to database!" << endl << addState.lastError().text(); db->rollback(); return false; } } // state IS in db else { // initial state has already been checked if( i == initial ) { // our work here is done db->rollback(); return true; } // get the db state's loop id ull termLoop = 0; if( testState.record().value("loop_id").isNull() ) { // join a non-loop state termLoopFromState.bindValue(":id", QVariant(i->pack())); if( !termLoopFromState.exec() ){ qCritical() << "Cannot retrieve terminal loop from state!" << endl << termLoopFromState.lastError().text(); db->rollback(); return false; } termLoop = termLoopFromState.record().value("termloop").toLongLong(); } else { // join a loop state termLoop = testState.record().value("loop_id").toLongLong(); } // update simulation table with merger point and term loop id updateSim.bindValue(":final", QVariant(i->pack())); updateSim.bindValue(":termloopid", QVariant(termLoop)); updateSim.bindValue(":id", QVariant(initial->pack())); if( !updateSim.exec() ){ qCritical() << "Cannot update sim with terminal info!" << endl << updateSim.lastError().text(); db->rollback(); return false; } // increment term loop instance count incrementLoop.bindValue(":id", termLoop); if( !incrementLoop.exec() ){ qCritical() << "Cannot increment loop instance count!" << endl << incrementLoop.lastError().text(); db->rollback(); return false; } // default case: break, complete the transaction, return true // includes self-looping state case break; } // end state presence branch } // end state loop // commit transaction db->commit(); // unlock simulation //locker.unlock(); return true; }