public void integrate() {
        // Add acceleration to velocity
        velocity.add(acceleration);
        
        // Copy velocity into delta vector
        Vector delta = velocity.copy();
        
        // Copy and expand the AABB for broadphase collision
        AABB broadphase = aabb.copy().expand(delta);
        
        // Obtain AABBs eligible for collision detection 
        ArrayList<AABB> aabbs = level.getCollisionBoxes(broadphase);
        
        // Sweep and move along every axis
        for (AABB aabb2 : aabbs)
            aabb.sweepAlongAxis(aabb2, delta, 1);
        position.add(0, delta.y, 0);
        
        for (AABB aabb2 : aabbs)
            aabb.sweepAlongAxis(aabb2, delta, 0);
        position.add(delta.x, 0, 0);
        
        for (AABB aabb2 : aabbs)
            aabb.sweepAlongAxis(aabb2, delta, 2);
        position.add(0, 0, delta.z);
        
        // Check if you are touching a ground
        onGround = (delta.y != velocity.y && velocity.y < 0);
        
        // Calculate amount of distance moved
        if(onGround)
            distanceMoved += delta.length();
        
        // Reset velocities to zero in case of collision
        if(velocity.x != delta.x) velocity.x = 0;
        if(velocity.y != delta.y) velocity.y = 0;
        if(velocity.z != delta.z) velocity.z = 0;
        
        // Apply air and ground friction
        velocity.scale(Level.FRICTION_AIR);
        if(onGround)
            velocity.scale(Level.FRICTION_GROUND);
        
        // Reset acceleration
        acceleration.set(0, 0, 0);
    }