Example #1
0
State * takeastep(State * previous_state) { // calculates the next state in the simulation
                                            // this is where the node::update funcs are called    

   State * state = new State;

   float deltas;
   node * ptr = previous_state->root->right;
   MatrixXf M = MatrixXf::Zero(3*(NUM-1)+1, 3*(NUM-1)+1); //genralized mass matrix for the entire system
   for(int i=0; i<3*(NUM-1); i+=3) {

      // diagonal entryies = 2*deltas, off diagonal = deltas
         deltas = ptr->right->material_coordinate - ptr->material_coordinate;
         M(i,i) += 2*deltas;
         M(i,i+1) += 2*deltas;
         M(i,i+2) += 2*deltas;
         M(i+1,i) += 2*deltas;
         M(i+2,i) += 2*deltas;
         M(i+1,i+1) += 2*deltas;
         M(i+1,i+2) += 2*deltas;
         M(i+1,i+2) += 2*deltas;
         M(i+2,i+2) += 2*deltas;

         if(i == 3*(NUM-2))
            break;

         M(i+3, i) += deltas;
         M(i+3, i+1) += deltas;
         M(i+3, i+2) += deltas;
         M(i+4, i) += deltas;
         M(i+5, i) += deltas;
         M(i+4, i+1) += deltas;
         M(i+4, i+1) += deltas;
         M(i+4, i+1) += deltas;
         M(i+5, i+2) += deltas;

         M(i, i+3) = deltas;
         M(i+1, i+3) = deltas;
         M(i+2, i+3) = deltas;
         M(i, i+4) = deltas;
         M(i, i+5) = deltas;
         M(i+1, i+4) = deltas;
         M(i+1, i+4) = deltas;
         M(i+1, i+4) = deltas;
         M(i+2, i+5) = deltas;

         M(i+3, i+3) += 2*deltas;
         M(i+3, i+4) += 2*deltas;
         M(i+3, i+5) += 2*deltas;
         M(i+4, i+3) += 2*deltas;
         M(i+5, i+3) += 2*deltas;
         M(i+4, i+4) += 2*deltas;
         M(i+4, i+5) += 2*deltas;
         M(i+5, i+4) += 2*deltas;
         M(i+5, i+5) += 2*deltas;

         ptr = ptr->right;
         i+=3;
   }
   
   node * right_of_e0 = linear_search(previous_state->e1->material_coordinate, previous_state->root);
   
   float alpha = (previous_state->e1->material_coordinate - right_of_e0->left->material_coordinate)/(right_of_e0->material_coordinate - right_of_e0->left->material_coordinate);
   Vector3f deltax = *(right_of_e0->world_x)-*(right_of_e0->left->world_x);
   float mss = deltax.dot(deltax)/(right_of_e0->material_coordinate - right_of_e0->left->material_coordinate);

   M(3*(NUM-1), 3*(NUM-1)) = 2*mss;
   M(3*(NUM-1)-3, 3*(NUM-1)) += -deltax.x();
   M(3*(NUM-1)-2, 3*(NUM-1)) += -deltax.y();
   M(3*(NUM-1)-1, 3*(NUM-1)) += -deltax.z();

   M(3*(NUM-1), 3*(NUM-1)-3) += -deltax.x();
   M(3*(NUM-1), 3*(NUM-1)-2) += -deltax.y();
   M(3*(NUM-1), 3*(NUM-1)-1) += -deltax.z();

   // force term : taking into account of gravity and spring potential energy
   VectorXf f = VectorXf(3*(NUM-1)+1);
   VectorXf qOldDot = VectorXf(3*(NUM-1)+1);
   VectorXf qOld = VectorXf(3*(NUM-1)+1);
   ptr = previous_state->root->right;
   Vector3f deltaXDotRight, deltaXDotLeft, deltaXRight, deltaXLeft, constant;
   float absDeltaXRight, absDeltaXLeft, restLengthRight, restLengthLeft;

   for(int i=0; i<3*(NUM-1); i+=3 ) {

      //putting in old values for Euler integration
      qOldDot[i] = ptr->world_x_dot->x();
      qOldDot[i+1] = ptr->world_x_dot->y();
      qOldDot[i+2] = ptr->world_x_dot->z();

      qOld[i] = ptr->world_x->x();
      qOld[i+1] = ptr->world_x->y();
      qOld[i+2] = ptr->world_x->z();

      //gravity
      f[i+1] = -g * ptr->rho * (ptr->material_coordinate - ptr->left->material_coordinate);

      //spring
      if(ptr != right_of_e0->left && ptr != right_of_e0) { //normal case

         deltaXDotRight = *(ptr->world_x_dot) - *(ptr->right->world_x_dot);
         deltaXDotLeft = *(ptr->world_x_dot) - *(ptr->left->world_x_dot);
         deltaXRight = *(ptr->world_x) - *(ptr->right->world_x);
         deltaXLeft = *(ptr->world_x) - *(ptr->left->world_x);

         absDeltaXRight = sqrt(deltaXRight.dot(deltaXRight));
         absDeltaXLeft = sqrt(deltaXLeft.dot(deltaXLeft));

         constant = -(ks * (absDeltaXLeft - l0) + kd * deltaXDotLeft.dot(deltaXLeft)/absDeltaXLeft)*deltaXLeft/absDeltaXLeft - (ks * (absDeltaXRight - l0) + kd * deltaXDotRight.dot(deltaXRight)/absDeltaXRight)*deltaXRight/absDeltaXRight;
         
      }
      else if(ptr == right_of_e0->left) { //ball's left node is ptr

         deltaXDotRight = *(ptr->world_x_dot) - *(previous_state->e1->world_x_dot);
         deltaXDotLeft = *(ptr->world_x_dot) - *(ptr->left->world_x_dot);
         deltaXRight = *(ptr->world_x) - *(previous_state->e1->world_x);
         deltaXLeft = *(ptr->world_x) - *(ptr->left->world_x);
         restLengthRight = l0 * alpha;
         restLengthRight = l0;
         
         if(deltaXRight.dot(deltaXRight) < 0.001) {
            deltaXDotRight = *(ptr->world_x_dot) - *(ptr->right->world_x_dot);
            deltaXRight = *(ptr->world_x) - *(ptr->right->world_x);
            restLengthLeft = l0;
         }
         
         absDeltaXRight = sqrt(deltaXRight.dot(deltaXRight));
         absDeltaXLeft = sqrt(deltaXLeft.dot(deltaXLeft));          
         constant = -(ks * (absDeltaXLeft - restLengthLeft) + kd * deltaXDotLeft.dot(deltaXLeft)/absDeltaXLeft)*deltaXLeft/absDeltaXLeft - (ks * (absDeltaXRight - restLengthRight) + kd * deltaXDotRight.dot(deltaXRight)/absDeltaXRight)*deltaXRight/absDeltaXRight;
      }
      else if(ptr == right_of_e0) { //ball's right node is ptr
         deltaXDotLeft = *(ptr->world_x_dot) - *(previous_state->e1->world_x_dot);
         deltaXDotRight = *(ptr->world_x_dot) - *(ptr->right->world_x_dot);
         deltaXLeft = *(ptr->world_x) - *(previous_state->e1->world_x);
         deltaXRight = *(ptr->world_x) - *(ptr->right->world_x);
         restLengthLeft = l0 * alpha;
         restLengthRight = l0;
         
         if(deltaXLeft.dot(deltaXLeft) < 0.001) {
            deltaXDotLeft = *(ptr->world_x_dot) - *(ptr->left->world_x_dot);
            deltaXLeft = *(ptr->world_x) - *(ptr->left->world_x);
            restLengthLeft = l0;
         }
         
         absDeltaXLeft = sqrt(deltaXLeft.dot(deltaXLeft));
         absDeltaXRight = sqrt(deltaXRight.dot(deltaXRight));
         constant = -(ks * (absDeltaXLeft - restLengthLeft) + kd * deltaXDotLeft.dot(deltaXLeft)/absDeltaXLeft)*deltaXLeft/absDeltaXLeft - (ks * (absDeltaXRight - restLengthRight) + kd * deltaXDotRight.dot(deltaXRight)/absDeltaXRight)*deltaXRight/absDeltaXRight;
      }
      
      f[i] += constant.x();
      f[i+1] += constant.y();
      f[i+2] += constant.z();

      f[i] = 0.0; f[i+2] = 0.0;
      ptr = ptr->right;
   }


   Vector3f x0_and_x1= (1-alpha)* *(right_of_e0->left->world_x) + alpha* *(right_of_e0->world_x);
    f[3*(NUM-1)] = previous_state->e1->rho * x0_and_x1.dot(Vector3f(0,-g,0)); 

   VectorXf rhs = M * qOldDot +  dt * f;
   VectorXf qNewDot;

   qNewDot = M.lu().solve(rhs);


   VectorXf qNew = qNewDot * dt + qOld;

   L3node * newRoot = new L3node(0.0, *(previous_state->root->world_x), *(previous_state->root->world_x_dot));
   state->root = newRoot;
   node * newPtr = state->root;
   ptr = previous_state->root->right;

   Vector3f newX, newXDot;

   //update the new state
   for(int i=0; i<3*(NUM-1); i+=3) {

      newX = Vector3f(qNew[i], qNew[i+1], qNew[i+2]);
      newXDot = Vector3f(qNewDot[i], qNewDot[i+1], qNewDot[i+2]);
      
      L3node * newNode = new L3node(ptr->material_coordinate, newX, newXDot);
      
      newPtr->right = newNode;
      newPtr->right->left = newPtr;
      
      ptr = ptr->right;
      newPtr = newPtr->right;
   }

   L3node* rightNode = new L3node(1.0, *(ptr->world_x), *(ptr->world_x_dot));
   newPtr->right = rightNode;
   newPtr->right->left = newPtr;

   cout << "qNew : " << qNew << "qDotNew: " << qNewDot << endl;
   right_of_e0 = linear_search(qNew[3*(NUM-1)], newRoot);
   alpha = (qNew[3*(NUM-1)] - right_of_e0->left->material_coordinate) / (right_of_e0->material_coordinate - right_of_e0->left->material_coordinate);
   newX = (1.0-alpha) * *(right_of_e0->left->world_x) + alpha * *(right_of_e0->world_x);
   newXDot = (1.0-alpha) * *(right_of_e0->left->world_x_dot) + alpha * *(right_of_e0->world_x_dot);

   E0node * newE = new E0node(qNew[3*(NUM-1)], qNewDot[3*(NUM-1)], newX, newXDot, newRoot);
   newE->rho = 2.0;
   state->e1 = newE;
   state->next = NULL;
   return state;

 /*
// state->e1 = dynamic_cast<E3node *> (previous_state->e1)->update();
 //state->e1 = dynamic_cast<L3node *> (previous_state->e1)->update();
 state->e1 = dynamic_cast<E0node *> (previous_state->e1)->update();
 state->root = dynamic_cast<E0node *> (state->e1)->rootNode;
 state->next = NULL;
 return state;
*/

}