File indexing completed on 2024-04-14 03:49:29

0001 /*
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "world.h"
0008 #include "solver.h"
0009 #include "collisionsolver.h"
0010 #include "constraintsolver.h"
0011 
0012 #include <algorithm>
0013 #include <cmath>
0014 #include <QtGlobal>
0015 
0016 namespace StepCore
0017 {
0018 
0019 
0020 STEPCORE_META_OBJECT(Tool, QT_TRANSLATE_NOOP("ObjectClass", "Tool"), QT_TRANSLATE_NOOP("ObjectDescription", "Tool"), MetaObject::ABSTRACT,,)
0021 
0022 STEPCORE_META_OBJECT(World, QT_TRANSLATE_NOOP("ObjectClass", "World"), QT_TRANSLATE_NOOP("ObjectDescription", "World"), 0, STEPCORE_SUPER_CLASS(ItemGroup),
0023         STEPCORE_PROPERTY_RW_D(double, time, QT_TRANSLATE_NOOP("PropertyName", "time"), QT_TRANSLATE_NOOP("Units", "s"), QT_TRANSLATE_NOOP("PropertyDescription", "Current time"), time, setTime)
0024         STEPCORE_PROPERTY_RW  (double, timeScale, QT_TRANSLATE_NOOP("PropertyName", "timeScale"), STEPCORE_UNITS_1, QT_TRANSLATE_NOOP("PropertyDescription", "Simulation speed scale"), timeScale, setTimeScale)
0025         STEPCORE_PROPERTY_RW  (bool, errorsCalculation, QT_TRANSLATE_NOOP("PropertyName", "errorsCalculation"), STEPCORE_UNITS_NULL,
0026                         QT_TRANSLATE_NOOP("PropertyDescription", "Enable global error calculation"), errorsCalculation, setErrorsCalculation))
0027 
0028 World::World()
0029     : _time(0), _timeScale(1), _errorsCalculation(false),
0030       _solver(nullptr), _collisionSolver(nullptr), _constraintSolver(nullptr),
0031       _variablesCount(0)
0032 {
0033     setColor(0xffffffff);
0034     setWorld(this);
0035     clear();
0036 }
0037 
0038 World::World(const World& world)
0039     : ItemGroup(), _time(0), _timeScale(1), _errorsCalculation(false),
0040       _solver(nullptr), _collisionSolver(nullptr), _constraintSolver(nullptr),
0041       _variablesCount(0)
0042 {
0043     *this = world;
0044 }
0045 
0046 World::~World()
0047 {
0048     clear();
0049 }
0050 
0051 void World::clear()
0052 {
0053     // Avoid erasing each element individually in the cache
0054     if(_collisionSolver) _collisionSolver->resetCaches();
0055 
0056     // clear _items
0057     ItemGroup::clear();
0058 
0059     STEPCORE_ASSERT_NOABORT(_bodies.empty());
0060     STEPCORE_ASSERT_NOABORT(_forces.empty());
0061     STEPCORE_ASSERT_NOABORT(_joints.empty());
0062     //_bodies.clear();
0063     //_forces.clear();
0064 
0065     delete _solver; _solver = nullptr;
0066     delete _collisionSolver; _collisionSolver = nullptr;
0067     delete _constraintSolver; _constraintSolver = nullptr;
0068 
0069     _variablesCount = 0;
0070     _variables.resize(0);
0071     _variances.resize(0);
0072     _tempArray.resize(0);
0073 
0074     _constraintsInfo.setDimension(0, 0);
0075 
0076     setColor(0xffffffff);
0077     deleteObjectErrors();
0078 
0079     _time = 0;
0080     _timeScale = 1;
0081     _errorsCalculation = false;
0082 
0083     _stopOnCollision = false;
0084     _stopOnIntersection = false;
0085     _evolveAbort = false;
0086 
0087 #ifdef STEPCORE_WITH_QT
0088     setName(QString());
0089 #endif
0090 }
0091 
0092 World& World::operator=(const World& world)
0093 {
0094     if(this == &world) return *this;
0095 
0096     clear();
0097     ItemGroup::operator=(world);
0098 
0099     if(world._solver) {
0100         setSolver(static_cast<Solver*>(
0101                 world._solver->metaObject()->cloneObject(*(world._solver))));
0102     } else setSolver(nullptr);
0103 
0104     if(world._collisionSolver) {
0105         setCollisionSolver(static_cast<CollisionSolver*>(
0106                world._collisionSolver->metaObject()->cloneObject(*(world._collisionSolver))));
0107     } else setCollisionSolver(nullptr);
0108 
0109     if(world._constraintSolver) setConstraintSolver(static_cast<ConstraintSolver*>(
0110                world._constraintSolver->metaObject()->cloneObject(*(world._constraintSolver))));
0111     else setConstraintSolver(nullptr);
0112 
0113     _time = world._time;
0114     _timeScale = world._timeScale;
0115     _errorsCalculation = world._errorsCalculation;
0116 
0117     _stopOnCollision = world._stopOnCollision;
0118     _stopOnIntersection = world._stopOnIntersection;
0119     _evolveAbort = world._evolveAbort;
0120 
0121     // Fix links
0122     QHash<const Object*, Object*> copyMap;
0123     copyMap.insert(NULL, NULL);
0124     copyMap.insert(&world, this);
0125     if(_solver) copyMap.insert(world._solver, _solver);
0126     if(_collisionSolver) copyMap.insert(world._collisionSolver, _collisionSolver);
0127     if(_constraintSolver) copyMap.insert(world._constraintSolver, _constraintSolver);
0128     fillCopyMap(&copyMap, &world, this);
0129 
0130     applyCopyMap(&copyMap, this);
0131     if(_solver) applyCopyMap(&copyMap, _solver);
0132     if(_collisionSolver) applyCopyMap(&copyMap, _collisionSolver);
0133     if(_constraintSolver) applyCopyMap(&copyMap, _constraintSolver);
0134 
0135     const ItemList::const_iterator end = items().end();
0136     for(ItemList::const_iterator it = items().begin(); it != end; ++it) {
0137         worldItemCopied(&copyMap, *it);
0138     }
0139 
0140     setWorld(this);
0141 
0142     checkVariablesCount();
0143 
0144     return *this;
0145 }
0146 
0147 void World::fillCopyMap(QHash<const Object*, Object*>* map,
0148                         const ItemGroup* g1, ItemGroup* g2)
0149 {
0150     const ItemList::const_iterator end = g1->items().end();
0151     for(ItemList::const_iterator it1 = g1->items().begin(),
0152                                  it2 = g2->items().begin();
0153                                  it1 != end; ++it1, ++it2) {
0154         map->insert(*it1, *it2);
0155         if((*it1)->metaObject()->inherits<StepCore::ItemGroup>())
0156             fillCopyMap(map, static_cast<ItemGroup*>(*it1), static_cast<ItemGroup*>(*it2));
0157     }
0158 }
0159 
0160 void World::applyCopyMap(QHash<const Object*, Object*>* map, Object* obj)
0161 {
0162     const StepCore::MetaObject* mobj = obj->metaObject();
0163     for(int i=0; i<mobj->propertyCount(); ++i) {
0164         const StepCore::MetaProperty* pr = mobj->property(i);
0165         if(pr->userTypeId() == qMetaTypeId<Object*>()) {
0166             QVariant v = pr->readVariant(obj);
0167             v = QVariant::fromValue(map->value(v.value<Object*>(), NULL));
0168             pr->writeVariant(obj, v);
0169         }
0170     }
0171 }
0172 
0173 void World::worldItemCopied(QHash<const Object*, Object*>* map, Item* item)
0174 {
0175     applyCopyMap(map, item);
0176 
0177     if(item->metaObject()->inherits<Force>())
0178         _forces.push_back(dynamic_cast<Force*>(item));
0179     if(item->metaObject()->inherits<Joint>())
0180         _joints.push_back(dynamic_cast<Joint*>(item));
0181     if(item->metaObject()->inherits<Body>())
0182         _bodies.push_back(dynamic_cast<Body*>(item));
0183 
0184     if(item->metaObject()->inherits<ItemGroup>()) {
0185         ItemGroup* group = static_cast<ItemGroup*>(item);
0186         ItemList::const_iterator end = group->items().end();
0187         for(ItemList::const_iterator it = group->items().begin(); it != end; ++it) {
0188             worldItemCopied(map, *it);
0189         }
0190     }
0191 }
0192 
0193 void World::worldItemAdded(Item* item)
0194 {
0195     if(item->metaObject()->inherits<Force>())
0196         _forces.push_back(dynamic_cast<Force*>(item));
0197 
0198     if(item->metaObject()->inherits<Joint>())
0199         _joints.push_back(dynamic_cast<Joint*>(item));
0200 
0201     if(item->metaObject()->inherits<Body>()) {
0202         Body* body = dynamic_cast<Body*>(item);
0203         _bodies.push_back(body);
0204         if(_collisionSolver) _collisionSolver->bodyAdded(_bodies, body);
0205     }
0206 
0207     if(item->metaObject()->inherits<ItemGroup>()) {
0208         ItemGroup* group = static_cast<ItemGroup*>(item);
0209         ItemList::const_iterator end = group->items().end();
0210         for(ItemList::const_iterator it = group->items().begin(); it != end; ++it) {
0211             worldItemAdded(*it);
0212         }
0213     }
0214 
0215     checkVariablesCount();
0216 }
0217 
0218 void World::worldItemRemoved(Item* item)
0219 {
0220     if(item->metaObject()->inherits<ItemGroup>()) {
0221         ItemGroup* group = static_cast<ItemGroup*>(item);
0222         ItemList::const_iterator end = group->items().end();
0223         for(ItemList::const_iterator it = group->items().begin(); it != end; ++it) {
0224             worldItemRemoved(*it);
0225         }
0226     }
0227 
0228     const ItemList::const_iterator end = items().end();
0229     for(ItemList::const_iterator it = items().begin(); it != end; ++it) {
0230         (*it)->worldItemRemoved(item);
0231     }
0232 
0233     if(item->metaObject()->inherits<Body>()) {
0234         Body* body = dynamic_cast<Body*>(item);
0235         if(_collisionSolver) _collisionSolver->bodyRemoved(_bodies, body);
0236         BodyList::iterator b = std::find(_bodies.begin(), _bodies.end(), body);
0237         STEPCORE_ASSERT_NOABORT(b != _bodies.end());
0238         _bodies.erase(b);
0239     }
0240 
0241     if(item->metaObject()->inherits<Joint>()) {
0242         JointList::iterator j = std::find(_joints.begin(), _joints.end(),
0243                                             dynamic_cast<Joint*>(item));
0244         STEPCORE_ASSERT_NOABORT(j != _joints.end());
0245         _joints.erase(j);
0246     }
0247 
0248     if(item->metaObject()->inherits<Force>()) {
0249         ForceList::iterator f = std::find(_forces.begin(), _forces.end(),
0250                                             dynamic_cast<Force*>(item));
0251         STEPCORE_ASSERT_NOABORT(f != _forces.end());
0252         _forces.erase(f);
0253     }
0254 
0255     // XXX: on ItemGroup::clear this will be called on each object !
0256     checkVariablesCount();
0257 }
0258 
0259 /*
0260 void World::addItem(Item* item)
0261 {
0262     _items.push_back(item);
0263     item->setWorld(this);
0264     Force* force = dynamic_cast<Force*>(item);
0265     if(force) _forces.push_back(force);
0266     Body* body = dynamic_cast<Body*>(item);
0267     if(body) _bodies.push_back(body);
0268 }
0269 */
0270 
0271 /*void World::removeItem(Item* item)
0272 {
0273     const ItemList::const_iterator it_end = _items.end();
0274     for(ItemList::iterator it = _items.begin(); it != it_end; ++it)
0275         (*it)->worldItemRemoved(item);
0276 
0277     item->setWorld(NULL);
0278 
0279     ItemList::iterator i = std::find(_items.begin(), _items.end(), item);
0280     STEPCORE_ASSERT_NOABORT(i != _items.end());
0281     _items.erase(i);
0282 
0283     Force* force = dynamic_cast<Force*>(item);
0284     if(force) {
0285         ForceList::iterator f = std::find(_forces.begin(), _forces.end(), force);
0286         STEPCORE_ASSERT_NOABORT(f != _forces.end());
0287         _forces.erase(f);
0288     }
0289 
0290     Body* body = dynamic_cast<Body*>(item);
0291     if(body) {
0292         BodyList::iterator b = std::find(_bodies.begin(), _bodies.end(), body);
0293         STEPCORE_ASSERT_NOABORT(b != _bodies.end());
0294         _bodies.erase(b);
0295     }
0296 }
0297 */
0298 
0299 /*
0300 int World::itemIndex(const Item* item) const
0301 {
0302     ItemList::const_iterator o = std::find(_items.begin(), _items.end(), item);
0303     STEPCORE_ASSERT_NOABORT(o != _items.end());
0304     return std::distance(_items.begin(), o);
0305 }
0306 */
0307 
0308 /*
0309 Item* World::item(const QString& name) const
0310 {
0311     for(ItemList::const_iterator o = _items.begin(); o != _items.end(); ++o) {
0312         if((*o)->name() == name) return *o;
0313     }
0314     return NULL;
0315 }
0316 */
0317 
0318 Object* World::object(const QString& name)
0319 {
0320     if(name.isEmpty()) return nullptr;
0321     if(this->name() == name) return this;
0322     else if(_solver && _solver->name() == name) return _solver;
0323     else if(_collisionSolver && _collisionSolver->name() == name) return _collisionSolver;
0324     else if(_constraintSolver && _constraintSolver->name() == name) return _constraintSolver;
0325     else return item(name);
0326 }
0327 
0328 void World::setSolver(Solver* solver)
0329 {
0330     delete _solver;
0331     _solver = solver;
0332     if(_solver != nullptr) {
0333         _solver->setDimension(_variablesCount*2);
0334         _solver->setFunction(solverFunction);
0335         _solver->setParams(this);
0336     }
0337 }
0338 
0339 Solver* World::removeSolver()
0340 {
0341     Solver* solver = _solver;
0342     _solver = nullptr;
0343     return solver;
0344 }
0345 
0346 void World::setCollisionSolver(CollisionSolver* collisionSolver)
0347 {
0348     delete _collisionSolver;
0349     _collisionSolver = collisionSolver;
0350 }
0351 
0352 CollisionSolver* World::removeCollisionSolver()
0353 {
0354     CollisionSolver* collisionSolver = _collisionSolver;
0355     _collisionSolver = nullptr;
0356     return collisionSolver;
0357 }
0358 
0359 void World::setConstraintSolver(ConstraintSolver* constraintSolver)
0360 {
0361     delete _constraintSolver;
0362     _constraintSolver = constraintSolver;
0363 }
0364 
0365 ConstraintSolver* World::removeConstraintSolver()
0366 {
0367     ConstraintSolver* constraintSolver = _constraintSolver;
0368     _constraintSolver = nullptr;
0369     return constraintSolver;
0370 }
0371 
0372 void World::checkVariablesCount()
0373 {
0374     int variablesCount = 0;
0375     for(BodyList::iterator b = _bodies.begin(); b != _bodies.end(); ++b) {
0376         (*b)->setVariablesOffset(variablesCount);
0377         variablesCount += (*b)->variablesCount();
0378     }
0379 
0380     int constraintsCount = 0;
0381     for(JointList::iterator j = _joints.begin(); j != _joints.end(); ++j) {
0382         constraintsCount += (*j)->constraintsCount();
0383     }
0384     
0385     _constraintsInfo.setDimension(variablesCount, constraintsCount, 0);
0386 
0387     if(variablesCount != _variablesCount) {
0388         _variablesCount = variablesCount;
0389         _variables.resize(_variablesCount*2);
0390         _variances.resize(_variablesCount*2);
0391         _tempArray.resize(_variablesCount*2);
0392         if(_solver) _solver->setDimension(_variablesCount*2);
0393     }
0394 }
0395 
0396 void World::gatherAccelerations(double* acceleration, double* accelerationVariance)
0397 {
0398     if(accelerationVariance)
0399         memset(accelerationVariance, 0, _variablesCount*sizeof(*accelerationVariance));
0400 
0401     int index = 0;
0402     const BodyList::const_iterator it_end = _bodies.end();
0403     for(BodyList::iterator b = _bodies.begin(); b != it_end; ++b) {
0404         (*b)->getAccelerations(acceleration + index, accelerationVariance ? accelerationVariance + index : nullptr);
0405         index += (*b)->variablesCount();
0406     }
0407 }
0408 
0409 void World::gatherVariables(double* variables, double* variances)
0410 {
0411     if(variances) memset(variances, 0, _variablesCount*2*sizeof(*variances));
0412 
0413     int index = 0;
0414     const BodyList::const_iterator it_end = _bodies.end();
0415     for(BodyList::iterator b = _bodies.begin(); b != it_end; ++b) {
0416         (*b)->getVariables(variables + index, variables + _variablesCount + index,
0417                            variances ? variances + index : nullptr,
0418                            variances ? variances + _variablesCount + index : nullptr);
0419         index += (*b)->variablesCount();
0420     }
0421 }
0422 
0423 void World::scatterVariables(const double* variables, const double* variances)
0424 {
0425     int index = 0;
0426     const BodyList::const_iterator it_end = _bodies.end();
0427     for(BodyList::iterator b = _bodies.begin(); b != it_end; ++b) {
0428         (*b)->setVariables(variables + index,  variables + _variablesCount + index,
0429                            variances ? variances + index : nullptr,
0430                            variances ? variances + _variablesCount + index : nullptr);
0431         index += (*b)->variablesCount();
0432     }
0433 }
0434 
0435 void World::gatherJointsInfo(ConstraintsInfo* info)
0436 {
0437     info->clear();
0438 
0439     int offset = 0;
0440     const BodyList::const_iterator b_end = _bodies.end();
0441     for(BodyList::iterator body = _bodies.begin(); body != b_end; ++body) {
0442         (*body)->getInverseMass(&(info->inverseMass), nullptr, offset);
0443         offset += (*body)->variablesCount();
0444     }
0445 
0446     offset = 0;
0447     const JointList::const_iterator j_end = _joints.end();
0448     for(JointList::iterator joint = _joints.begin(); joint != j_end; ++joint) {
0449         (*joint)->getConstraintsInfo(info, offset);
0450         offset += (*joint)->constraintsCount();
0451     }
0452 }
0453 
0454 int World::doCalcFn()
0455 {
0456     STEPCORE_ASSERT_NOABORT(_solver != nullptr);
0457 
0458     //if(_collisionSolver) _collisionSolver->resetCaches();
0459 
0460     _stopOnCollision = false;
0461     _stopOnIntersection = false;
0462     checkVariablesCount();
0463     gatherVariables(_variables.data(), _errorsCalculation ? _variances.data() : nullptr);
0464     return _solver->doCalcFn(&_time, &_variables, _errorsCalculation ? &_variances : nullptr,
0465                              nullptr, _errorsCalculation ? &_variances : nullptr);
0466 }
0467 
0468 int World::doEvolve(double delta)
0469 {
0470     STEPCORE_ASSERT_NOABORT(_solver != nullptr);
0471     
0472     checkVariablesCount();
0473     gatherVariables(_variables.data(), _errorsCalculation ? _variances.data() : nullptr);
0474 
0475     int ret = Solver::OK;
0476     double targetTime = _time + delta*_timeScale;
0477     
0478     if(_collisionSolver) {
0479         //_collisionSolver->resetCaches();
0480         if(Contact::Intersected == _collisionSolver->checkContacts(_bodies))
0481             return Solver::IntersectionDetected;
0482     }
0483 
0484     while(_time < targetTime) {
0485         STEPCORE_ASSERT_NOABORT( targetTime - _time > _solver->stepSize() / 1000 );
0486         if( !(   targetTime - _time > _solver->stepSize() / 1000 ) ) {
0487                     qDebug("* %e %e %e", targetTime, _time, _solver->stepSize());
0488         }
0489         double time = _time;
0490 
0491         _stopOnCollision = true;
0492         _stopOnIntersection = true;
0493         
0494         ret = _solver->doEvolve(&time, targetTime, &_variables,
0495                             _errorsCalculation ? &_variances : nullptr);
0496         
0497         _time = time;
0498 
0499         if(ret == Solver::CollisionDetected ||
0500            ret == Solver::IntersectionDetected) {
0501             // If we have stopped on collision
0502             // 1. Decrease timestep to stop before collision
0503             // 2. Proceed with decreased timestep until
0504             //    - we have meet collision again: go to 1
0505             //    - we pass collision point: it means that we have come close enough
0506             //      to collision point and CollisionSolver have resolved collision
0507             // We can't simply change Solver::stepSize since adaptive solvers can
0508             // abuse our settings so we have to step manually
0509             //STEPCORE_ASSERT_NOABORT(_collisionTime <= targetTime);
0510             //STEPCORE_ASSERT_NOABORT(_collisionTime > _time);
0511             double stepSize = fmin(_solver->stepSize() / 2, targetTime - _time);
0512             double collisionEndTime = targetTime - _time > stepSize*3.01 ? _time + stepSize*3 : targetTime;
0513 
0514             _stopOnCollision = false;
0515 
0516             do {
0517                 double endTime = collisionEndTime - time > stepSize*1.01 ? time+stepSize : collisionEndTime;
0518 
0519                 ret = _solver->doEvolve(&time, endTime, &_variables,
0520                             _errorsCalculation ? &_variances : nullptr);
0521                 
0522                 _time = time;
0523 
0524                 if(ret == Solver::IntersectionDetected || ret == Solver::CollisionDetected) {
0525                     //STEPCORE_ASSERT_NOABORT(_collisionTime > _time);
0526                     //STEPCORE_ASSERT_NOABORT(_collisionTime < _collisionExpectedTime);
0527                     stepSize = fmin(stepSize/2, targetTime - _time);
0528                     collisionEndTime = targetTime - _time > stepSize*3.01 ? _time + stepSize*3 : targetTime;
0529 
0530                     //STEPCORE_ASSERT_NOABORT(_time + stepSize != _time);
0531                     // XXX: what to do if stepSize becomes too small ?
0532 
0533                 } else if(ret == Solver::OK) {
0534                     // We can be close to the collision point.
0535                     //
0536                     // Now we will calculate impulses required to fix collisions.
0537                     // All joints should be taken into account, but since we are
0538                     // calculating impulses we should "froze" the jacobian i.e.
0539                     // ignore it derivative
0540                     scatterVariables(_variables.data(), _errorsCalculation ? _variances.data() : nullptr);
0541                     
0542                     // check and count contacts before the sparse matrix assembly
0543                     int contactsCount = 0;
0544                     int status = _collisionSolver->checkContacts(_bodies, true, &contactsCount);
0545                     if (contactsCount!=_constraintsInfo.contactsCount)
0546                     {
0547                       _constraintsInfo.setDimension(_constraintsInfo.variablesCount,
0548                                                     _constraintsInfo.constraintsCount,
0549                                                     contactsCount);
0550                     }
0551                     
0552                     _tempArray.setZero();
0553                     ::new (&_constraintsInfo.position) MappedVector(_variables.data(), _variablesCount);
0554                     ::new (&_constraintsInfo.velocity) MappedVector(_variables.data()+_variablesCount, _variablesCount);
0555                     ::new (&_constraintsInfo.acceleration) MappedVector(_tempArray.data(), _variablesCount);
0556                     
0557                     // start sparse matrix assembly
0558                     gatherJointsInfo(&_constraintsInfo);
0559                     _constraintsInfo.jacobianDerivative.setZero();
0560                     
0561                     if(status >= CollisionSolver::InternalError) { ret = status; goto out; }
0562                     
0563                     _collisionSolver->getContactsInfo(_constraintsInfo, true);
0564                     // end sparse matrix assembly
0565 
0566                     if(_constraintsInfo.collisionFlag) {
0567                         ret = _constraintSolver->solve(&_constraintsInfo);
0568                         if(ret != Solver::OK) goto out;
0569 
0570                         // XXX: variances
0571                         _constraintsInfo.velocity += _constraintsInfo.inverseMass.asDiagonal() * _constraintsInfo.force;
0572                     }
0573                 } else goto out;
0574 
0575             } while(_time + stepSize/100 <= collisionEndTime); // XXX
0576         } else if(ret != Solver::OK) goto out;
0577     }
0578 
0579 out:
0580     scatterVariables(_variables.data(), _errorsCalculation ? _variances.data() : nullptr);
0581     return ret;
0582 }
0583 
0584 inline int World::solverFunction(double t, const double* y,
0585                     const double* yvar, double* f, double* fvar)
0586 {
0587     if(_evolveAbort) return Solver::Aborted;
0588 
0589     _time = t;
0590     scatterVariables(y, yvar); // this will reset force
0591 
0592     // 1. Forces
0593     bool calcVariances = (fvar != nullptr);
0594     const ForceList::const_iterator f_end = _forces.end();
0595     for(ForceList::iterator force = _forces.begin(); force != f_end; ++force) {
0596         (*force)->calcForce(calcVariances);
0597     }
0598     
0599     std::memcpy(f, y+_variablesCount, _variablesCount*sizeof(*f));
0600     if(fvar) std::memcpy(fvar, y+_variablesCount, _variablesCount*sizeof(*fvar));
0601     gatherAccelerations(f+_variablesCount, fvar ? fvar+_variablesCount : nullptr);
0602     
0603     if (_constraintSolver)
0604     {
0605       // setup...
0606       
0607       // check contacts
0608       int state = 0;
0609       if(_collisionSolver) {
0610           int contactsCount = 0;
0611           state = _collisionSolver->checkContacts(_bodies, false, &contactsCount);
0612           
0613           if (contactsCount!=_constraintsInfo.contactsCount)
0614           {
0615             _constraintsInfo.setDimension(_constraintsInfo.variablesCount,
0616                                           _constraintsInfo.constraintsCount,
0617                                           contactsCount);
0618           }
0619       }
0620 
0621       if(_variablesCount>0)
0622       {
0623         ::new (&_constraintsInfo.position) Eigen::Map<const Eigen::VectorXd>(y, _variablesCount);
0624         ::new (&_constraintsInfo.velocity) Eigen::Map<const Eigen::VectorXd>(y+_variablesCount, _variablesCount);
0625         ::new (&_constraintsInfo.acceleration) Eigen::Map<Eigen::VectorXd>(f+_variablesCount, _variablesCount);
0626       }
0627 
0628       // end sparse matrix assembly
0629       
0630       // 2. Joints
0631       gatherJointsInfo(&_constraintsInfo);
0632 
0633       // 3. Collisions (TODO: variances for collisions)
0634       if(_collisionSolver) {
0635           _collisionSolver->getContactsInfo(_constraintsInfo, false);
0636           if(state == Contact::Intersected) {
0637               if(_stopOnIntersection) return Solver::IntersectionDetected;
0638           } else {
0639               if(state == Contact::Colliding) {
0640                   if(_stopOnCollision) return Solver::CollisionDetected;
0641                   // XXX: We are not stopping on colliding contact
0642                   // and resolving them only at the end of timestep
0643                   // XXX: is it right solution ? Shouldn't we try to find
0644                   // contact point more exactly for example using binary search ?
0645                   //_collisionTime = t;
0646                   //_collisionTime = t;
0647                   //if(t < _collisionExpectedTime)
0648                   //    return DantzigLCPCollisionSolver::CollisionDetected;
0649               } else if(state >= CollisionSolver::InternalError) {
0650                   return state;
0651               }
0652           }
0653       }
0654       // end sparse matrix assembly
0655 
0656       // 4. Solve constraints
0657       if(_constraintsInfo.constraintsCount + _constraintsInfo.contactsCount > 0) {
0658 
0659           int state = _constraintSolver->solve(&_constraintsInfo);
0660           if(state != Solver::OK) return state;
0661 
0662           int offset = 0;
0663           const BodyList::const_iterator b_end = _bodies.end();
0664           for(BodyList::iterator body = _bodies.begin(); body != b_end; ++body) {
0665               (*body)->addForce(&_constraintsInfo.force[offset], nullptr);
0666               (*body)->getAccelerations(f+_variablesCount+offset, nullptr);
0667               offset += (*body)->variablesCount();
0668           }
0669       }
0670     }
0671 
0672     return 0;
0673 }
0674 
0675 int World::solverFunction(double t, const double* y,
0676                 const double* yvar, double* f, double* fvar, void* params)
0677 {
0678     return static_cast<World*>(params)->solverFunction(t, y, yvar, f, fvar);
0679 }
0680 
0681 } // namespace StepCore
0682