int main() {
    WorldParameters parameters;
    parameters.setWorldMinMax(Vector3(-1000, -1000, -1000), Vector3(50000, 50000, 50000));
    World world(parameters);

    std::vector<Proxy*> boxes;

    int countPerDimension = 10;
    int proxyCount = countPerDimension * countPerDimension * countPerDimension;
    Vector3 boxSize = Vector3(10.0, 10.0, 10.0);
    Vector3 boxOffset = Vector3(10.0, 10.0, 10.0); // distance between two boxes
    boxes = createManyRigidBoxes(&world, boxSize, proxyCount);

    int box = 0;
    Vector3 dist = boxSize + boxOffset;
    for (int x = 0; x < countPerDimension; x++) {
        for (int y = 0; y < countPerDimension; y++) {
            for (int z = 0; z < countPerDimension; z++) {
                Proxy* p = boxes.at(box);

                p->translate(dist.getX() * x,
                        dist.getY() * y,
                        dist.getZ() * z);

                box++;
            }
        }
    }

    world.prepareSimulation();


    std::vector<Vector3> translationPerStep;
    translationPerStep.reserve(proxyCount);

    /*
     * 0 = constant translation for all proxies
     * 1 = disable movement
     */
    int translationMode = 0;
    switch (translationMode) {
        case 0: // constant translation
        {
            Vector3 translation = Vector3(1.0, 1.0, 1.0);
            for (int i = 0; i < proxyCount; i++) {
                translationPerStep.push_back(translation);
            }
            break;
        }
        case 1:
         break;
        default:
            error() << "unknown translationMode " << translationMode;
            return 1;
    }

    /*
     * >= 0: do that many iterations
     *  < 0: do infinite iterations
     */
    int maxIterations = 20;
    bool useThreads = true;

    debug() << "starting collision detection with " << proxyCount << " proxies";
    int reverseMovementCounter = 0;
    for (int iteration = 0; maxIterations < 0 || iteration < maxIterations; iteration++) {
        // move all proxies by one step
        for (int i = 0; i < proxyCount; i++) {
            boxes[i]->translate(translationPerStep[i]);
        }
        reverseMovementCounter++;
        if (reverseMovementCounter > 100) {
            reverseMovementCounter = 0;
            for (std::vector<Vector3>::iterator it = translationPerStep.begin(); it != translationPerStep.end(); ++it) {
                (*it) = (*it) * -1;
            }
        }


        unsigned int flags = World::COLLISIONFLAG_SKIP_MIDDLE_PHASE;
        if (useThreads) {
            flags |= World::COLLISIONFLAG_USE_THREADS;
        }
        world.calculateAllCollisions(flags);

        if (world.getDebugLog()) {
//            world.getDebugLog()->printSummary();
        }
    }

    return 0;
}
Exemple #2
0
    void WorldTest::simulationTestUncached() {
        World* world = new World(Vector3(200000, 200000, 200000));
        world->setUseCollisionCaching(false);
        Vector3 boxDimensions(10, 10, 10);
        Proxy* box1 = world->createProxy(new Box(boxDimensions));
        //Proxy* childBox = world->createProxy(new Box(boxDimensions));
        //childBox->translate(5, 5, 5);
        //box->addChild(childBox);

        world->addProxy(box1);

        Proxy* box2 = world->createProxy(new Box(boxDimensions));
        box2->translate(0, -20, 0);
        world->addProxy(box2);

        Proxy* box3 = world->createProxy(new Box(boxDimensions)); //always colliding with box2
        box3->translate(5, -25, 0);
        world->addProxy(box3);

        
        Proxy* moveBox = world->createProxy(new Box(Vector3(10, 50, 10)));
        moveBox->translate(20, -25, 0); //starting in no-collision state
        world->addProxy(moveBox);

        //WorldCollisions coll;
        
        world->prepareSimulation();
//std::cout << "-----------Starting simulation test-----------"<<std::endl;
//std::cout << "doing pre-move collisionCheck"<<std::endl;
        //test and ensure 1 BPC and rigid C
        WorldCollisions coll0 = world->calculateAllCollisions();
        CPPUNIT_ASSERT_EQUAL(1,
                (int)coll0.getBroadPhaseCollisions()->getResults().size());
        CPPUNIT_ASSERT_EQUAL(1, (int)coll0.getRigidBoundingVolumeCollisions().size());

        //Step 1 -> move moveBox to collidy with box3
//std::cout <<std::endl<< "doing step 1 - move in to collide with box3"<<std::endl;
        moveBox->translate(-6, 0, 0);

        //ensure 2 BPC/RC
        WorldCollisions coll1  = world->calculateAllCollisions();
        CPPUNIT_ASSERT_EQUAL(2,
                (int)coll1.getBroadPhaseCollisions()->getResults().size());
        CPPUNIT_ASSERT_EQUAL(2, (int)coll1.getRigidBoundingVolumeCollisions().size());

        //Step 2-> move to collide with all boxes
//std::cout <<std::endl<<"doing step 2 - move further to collide with all"<<std::endl;
        moveBox->translate(-5, 0, 0);
        //ensure 4 collisions
        WorldCollisions coll2  = world->calculateAllCollisions();
        CPPUNIT_ASSERT_EQUAL(4,
                (int)coll2.getBroadPhaseCollisions()->getResults().size());
        CPPUNIT_ASSERT_EQUAL(4, (int)coll2.getRigidBoundingVolumeCollisions().size());

        //Step 3-> move out again
//std::cout << std::endl<<"doing step 3 - moving out"<<std::endl;
        moveBox->translate(11, 0, 0);
        //ensure 1 collisions
        WorldCollisions coll3  = world->calculateAllCollisions();
        CPPUNIT_ASSERT_EQUAL(1,
                (int)coll3.getBroadPhaseCollisions()->getResults().size());
        CPPUNIT_ASSERT_EQUAL(1, (int)coll3.getRigidBoundingVolumeCollisions().size());

        //Step 4-> move in again
//std::cout << std::endl<<"doing step 4 - moving back in"<<std::endl;
        moveBox->translate(-11, 0, 0);
        //ensure 4 collisions
        WorldCollisions coll4  = world->calculateAllCollisions();
        CPPUNIT_ASSERT_EQUAL(4,
                (int)coll4.getBroadPhaseCollisions()->getResults().size());
        CPPUNIT_ASSERT_EQUAL(4, (int)coll4.getRigidBoundingVolumeCollisions().size());

        delete world;
    }
Exemple #3
0
void UndoTest::testUndo() {
    // we maintain 2 World objects, a "undo" World and a "reference" world
    //
    // we will do some changes on both worlds and then do some changes on
    // the "undo" world only. after calling undo, both worlds should be
    // synced again.
    //
    // whenever we start tests, both worlds should be synced.
    World undoWorld;
    World referenceWorld;

    // add simple proxies and never move them
    // this tests in particular that a undoStep() call does not change
    // things that shouldnt change
    undoWorld.addProxy(undoWorld.createProxy(new Box(10, 10, 10)));
    referenceWorld.addProxy(referenceWorld.createProxy(new Box(10, 10, 10)));

    // add simple proxies, move them before adding, never move them
    // afterwards
    // this tests in particular that a undoStep() call does not change
    // things that shouldnt change
    Proxy* staticUndoProxy = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* staticRefereceProxy = referenceWorld.createProxy(new Box(10, 10, 10));
    staticUndoProxy->translate(-10, 10, 5);
    staticRefereceProxy->translate(-10, 10, 5);
    undoWorld.addProxy(staticUndoProxy);
    referenceWorld.addProxy(staticRefereceProxy);

    // add simple proxies, but move them before adding
    Proxy* proxyUndoWorld = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* proxyReferenceWorld = referenceWorld.createProxy(new Box(10, 10, 10));
    proxyUndoWorld->translate(-10, 10, 5);
    proxyReferenceWorld->translate(-10, 10, 5);
    undoWorld.addProxy(proxyUndoWorld);
    referenceWorld.addProxy(proxyReferenceWorld);

    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));
    undoWorld.startNextStep();
    referenceWorld.startNextStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo simple translations
    proxyUndoWorld->translate(100, 100, 100);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo multiple translations
    proxyUndoWorld->translate(100, 100, 100);
    proxyUndoWorld->translate(100, 300, 200);
    proxyUndoWorld->translate(100, 400, 500);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo simple rotations
    proxyUndoWorld->rotate(45, 1, 0, 0);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo multiple simple rotations
    proxyUndoWorld->rotate(45, 1, 0, 0);
    proxyUndoWorld->rotate(15, 1, 0, 0);
    proxyUndoWorld->rotate(45, 0, 1, 0);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo translations and rotations
    proxyUndoWorld->translate(100, 100, 100);
    proxyUndoWorld->rotate(45, 1, 0, 0);
    proxyUndoWorld->translate(100, 1, 100);
    proxyUndoWorld->rotate(15, 1, 0, 0);
    proxyUndoWorld->translate(100, 20, 100);
    proxyUndoWorld->rotate(45, 0, 1, 0);
    proxyUndoWorld->translate(100, 100, 400);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo setTransformation()
    Matrix m;
    m.translate(100, 0, 0);
    proxyUndoWorld->setTransformation(m);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo multiple setTransformation()
    m = Matrix();
    m.translate(100, 0, 0);
    proxyUndoWorld->setTransformation(m);
    m.translate(0, 50, 0);
    proxyUndoWorld->setTransformation(m);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo setProxyType()
    proxyUndoWorld->setProxyType(PROXYTYPE_DEFORMABLE);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // undo multiple setProxyType()
    proxyUndoWorld->setProxyType(PROXYTYPE_DEFORMABLE);
    proxyUndoWorld->setProxyType(PROXYTYPE_FIXED);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));


    ////////////////////////////////////////////////////////////////
    // build up a simple hierarchy with static + non-static children
    ////////////////////////////////////////////////////////////////
    Proxy* staticChildUndoWorld = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* staticChildReferenceWorld = referenceWorld.createProxy(new Box(10, 10, 10));
    staticChildUndoWorld->translate(40, 10, 10);
    staticChildReferenceWorld->translate(40, 10, 10);
    proxyUndoWorld->addChild(staticChildUndoWorld);
    proxyReferenceWorld->addChild(staticChildReferenceWorld);

    Proxy* childUndoWorld = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* childReferenceWorld = referenceWorld.createProxy(new Box(10, 10, 10));
    childUndoWorld->translate(0, 0, 10);
    childReferenceWorld->translate(0, 0, 10);
    childUndoWorld->rotate(100, 0, 0, 1);
    childReferenceWorld->rotate(100, 0, 0, 1);
    proxyUndoWorld->addChild(childUndoWorld);
    proxyReferenceWorld->addChild(childReferenceWorld);

    Proxy* staticGrandChildUndoWorld = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* staticGrandChildReferenceWorld = referenceWorld.createProxy(new Box(10, 10, 10));
    staticGrandChildUndoWorld->translate(20, 10, 10);
    staticGrandChildReferenceWorld->translate(20, 10, 10);
    childUndoWorld->addChild(staticGrandChildUndoWorld);
    childReferenceWorld->addChild(staticGrandChildReferenceWorld);
    ////////////////////////////////////
    // build up a simple hierarchy (end)
    ////////////////////////////////////

    // sanity check
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // adding child proxies should not have any influence on undo, i.e. undo
    // should be a noop here.
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    Proxy* dummyUndoProxy = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* dummyReferenceProxy = referenceWorld.createProxy(new Box(10, 10, 10));
    undoWorld.addProxy(dummyUndoProxy);
    referenceWorld.addProxy(dummyReferenceProxy);

    // another check that the addProxy() did not change anything
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    //////////////////////////////////////
    // add grand-children to the hierarchy
    //////////////////////////////////////
    Proxy* grandChildUndoWorld = undoWorld.createProxy(new Box(10, 10, 10));
    Proxy* grandChildReferenceWorld = referenceWorld.createProxy(new Box(10, 10, 10));
    grandChildUndoWorld->translate(0, 0, 100);
    grandChildReferenceWorld->translate(0, 0, 100);
    grandChildUndoWorld->rotate(100, 0, 0, 1);
    grandChildReferenceWorld->rotate(100, 0, 0, 1);
    childUndoWorld->addChild(grandChildUndoWorld);
    childReferenceWorld->addChild(grandChildReferenceWorld);
    ////////////////////////////////////////////
    // add grand-children to the hierarchy (end)
    ////////////////////////////////////////////

    // check that grand-children adding did not change anything
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // check for undo on children
    childUndoWorld->translate(60, 0, 0);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // check for undo on grand-children
    grandChildUndoWorld->translate(60, 0, 0);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // check for undo on the whole hierarchy
    proxyUndoWorld->translate(5, 5, 5);
    childUndoWorld->rotate(54, 1, 0, 0);
    m = Matrix();
    m.translate(10, 10, 10);
    m.rotate(44, 1, 0, 0);
    grandChildUndoWorld->setTransformation(m);
    grandChildUndoWorld->translate(60, 0, 0);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));


    // check that removeProxy() is NOT undone
    undoWorld.removeProxy(dummyUndoProxy);
    referenceWorld.removeProxy(dummyReferenceProxy);
    delete dummyUndoProxy;
    delete dummyReferenceProxy;
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));


    proxyUndoWorld->translate(10, 10, 10);
    proxyReferenceWorld->translate(10, 10, 10);
    // undo should cause the worlds NOT to be equal
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(false, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    proxyUndoWorld->translate(10, 10, 10);
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // check that that startNextStep() actually works as intended, i.e. we undo
    // the things _after_ the startNextStep(), not the ones before
    undoWorld.startNextStep();
    // startNextStep() should not undo anything (except the moveflags)
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // startNextStep() should clear all possible "undo" values, i.e. this
    // should be a noop
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // things _after_ a startNextStep() should be undone again
    proxyUndoWorld->translate(10, 10, 10);
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // check that removing of grand-children does not change anything
    childUndoWorld->removeChild(grandChildUndoWorld);
    childReferenceWorld->removeChild(grandChildReferenceWorld);
    delete grandChildUndoWorld;
    delete grandChildReferenceWorld;
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // check that calls to startNextStep() after removeChild() still works
    undoWorld.startNextStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));
    undoWorld.undoStep();
    CPPUNIT_ASSERT_EQUAL(true, checkWorldsAreEqual(&undoWorld, &referenceWorld));

    // TODO: check that deformations are un-done?
    //       open question: do we want to support un-doing of deformations?
}