Biomechanical Joint Model
 Author: Anderson Maciel

VInternal.cpp

Go to the documentation of this file.
00001 /************************************************************************\
00002 
00003   Copyright 1997 The University of North Carolina at Chapel Hill.
00004   All Rights Reserved.
00005 
00006   Permission to use, copy, modify and distribute this software
00007   and its documentation for educational, research and non-profit
00008   purposes, without fee, and without a written agreement is
00009   hereby granted, provided that the above copyright notice and
00010   the following three paragraphs appear in all copies.
00011 
00012   IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL
00013   HILL BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
00014   INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
00015   ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
00016   EVEN IF THE UNIVERSITY OF NORTH CAROLINA HAVE BEEN ADVISED OF
00017   THE POSSIBILITY OF SUCH DAMAGES.
00018 
00019 
00020   Permission to use, copy, modify and distribute this software
00021   and its documentation for educational, research and non-profit
00022   purposes, without fee, and without a written agreement is
00023   hereby granted, provided that the above copyright notice and
00024   the following three paragraphs appear in all copies.
00025 
00026   THE UNIVERSITY OF NORTH CAROLINA SPECIFICALLY DISCLAIM ANY
00027   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00028   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029   PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
00030   BASIS, AND THE UNIVERSITY OF NORTH CAROLINA HAS NO OBLIGATION
00031   TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
00032   MODIFICATIONS.
00033 
00034 
00035    --------------------------------- 
00036   |Please send all BUG REPORTS to:  |
00037   |                                 |
00038   |   geom@cs.unc.edu               |
00039   |                                 |
00040    ---------------------------------
00041   
00042      
00043   The authors may be contacted via:
00044 
00045   US Mail:  A. Pattekar/J. Cohen/T. Hudson/S. Gottschalk/M. Lin/D. Manocha
00046             Department of Computer Science
00047             Sitterson Hall, CB #3175
00048             University of N. Carolina
00049             Chapel Hill, NC 27599-3175
00050             
00051   Phone:    (919)962-1749
00052             
00053   EMail:    geom@cs.unc.edu
00054 
00055 \************************************************************************/
00056 
00057 /************************************************************************\
00058 Filename: VInternal.C
00059 --
00060 Description: This file implements the member functions of the class vinternal.c
00061 
00062 \************************************************************************/
00063 
00064 
00065 
00066 #include <iostream>
00067 #include <string.h>     //for memset and memcpy.
00068 #include "VInternal.H"
00069 
00070 const int DEFAULT_SIZE=10; //some arbitrary default size for "vc_objects" array.
00071 
00072 //error codes returned by VCollide API.
00073 //these are multiply defined in the files VCollide.H and VCollide.h
00074 //so, any changes to these need to be reflected in all three places.
00075 const int VC_ERR_INVALID_ID            = -4; //invalid id was passed to the
00076                                              //routine.
00077 const int VC_ERR_EMPTY_OBJECT          = -3; //EndObject called without adding
00078                                              //adding any triangles.
00079 const int VC_ERR_CALL_OUT_OF_SEQUENCE  = -2; //calls out of sequence.
00080 const int VC_ERR                       = -1; //some other error.
00081 const int VC_OK                        =  1; //No error.
00082 
00083 #ifndef _VCREPORTTYPE
00084 #define _VCREPORTTYPE
00085 struct VCReportType
00086 {
00087   int id1, id2;
00088 };
00089 #endif
00090 
00091 VCInternal::VCInternal()
00092 {
00093   state = VCstate_default;
00094   next_id = 0;
00095   
00096   size = DEFAULT_SIZE;                   //set the size of the array.
00097   vc_objects = new VCObject*[size]; //allocate the array.
00098   int i;
00099   for (i=0; i<size; i++)
00100     vc_objects[i] = NULL;
00101   
00102   disabled.Clear();  //to begin with, no pairs are disabled.
00103 }
00104 
00105 
00106 VCInternal::~VCInternal()
00107 {
00108 
00109   //deallocate the memory.
00110   int i;
00111   for (i=0; i<size; i++)
00112     {
00113       if (vc_objects[i])
00114         {
00115           delete vc_objects[i]->b;
00116           delete vc_objects[i];
00117         }
00118     }
00119   delete [] vc_objects;
00120 }
00121 
00122 
00123 
00124 int VCInternal::NewObject(int *id) //create a new object in the database.
00125 {
00126   //check if we are in the correct state.
00127   if (state != VCstate_default)
00128     {
00129       //cout<<"state is: "<<state<<"\n";
00130       return VC_ERR_CALL_OUT_OF_SEQUENCE;
00131     }
00132   state = VCstate_newObject; //set the new state.
00133 
00134   //increase the size of the "vc_objects" array if required.
00135   if (next_id >= size) 
00136     {
00137       int newsize = (next_id >= 2*size) ? (next_id+1) : 2*size;
00138       VCObject **temp = new VCObject*[newsize];
00139       int i;
00140       for (i=0; i<size; i++)
00141         temp[i] = vc_objects[i];
00142       for (i=size; i<newsize; i++)
00143         temp[i] = NULL;
00144       delete [] vc_objects;
00145       vc_objects = temp;
00146       size = newsize;
00147       
00148     }
00149   
00150   //allocate a new object.
00151   vc_objects[next_id] = new VCObject;
00152   if (vc_objects[next_id] == NULL)
00153     return VC_ERR;
00154   
00155   *id = next_id;  //for returning the id generated by VCollide.
00156   current_id = next_id;
00157   vc_objects[next_id]->id = next_id;
00158   vc_objects[next_id]->b = new RAPID_model;
00159   vc_objects[next_id]->b->BeginModel();
00160   vc_objects[next_id]->activation_state = 1;
00161   next_id++; 
00162   
00163   return VC_OK;
00164 }
00165 
00166 int VCInternal::AddTri(double v1[], double v2[], double v3[]) 
00167 {                     //add geometry to the newly created object.
00168 
00169   //check whether we are in the correct state.
00170   if ( (state != VCstate_newObject) && (state != VCstate_addTri) )
00171     {
00172       //cout<<"state is: "<<state<<"\n";
00173       return VC_ERR_CALL_OUT_OF_SEQUENCE;
00174     }
00175 
00176   state=VCstate_addTri; //set the new state.
00177 
00178   vc_objects[current_id]->b->AddTri(v1, v2, v3, 0);  //add triangle.
00179   return VC_OK;
00180   
00181 }
00182 
00183 
00184 int VCInternal::EndObject(void)
00185 {   //tells VCollide that inputting the geometry is complete.
00186 
00187   //check whether we are in the correct state.
00188   if (state == VCstate_newObject)
00189     return VC_ERR_EMPTY_OBJECT;
00190   else if (state != VCstate_addTri)
00191     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00192 
00193   state = VCstate_default;  //set the new state.
00194 
00195 
00196   //add the object to the NBody database.
00197   nbody.AddObject(current_id, vc_objects[current_id]->b);
00198   
00199   //now, have RAPID build the OBB tree.
00200   vc_objects[current_id]->b->EndModel();
00201 
00202   //initialize the transformation matrix to identity.
00203   //doing it the following way is probably faster, since the
00204   //compiler can use lower level memory calls for initialization.
00205   memset( ( (void *)vc_objects[current_id]->trans), 0, 16*sizeof(double) );
00206   vc_objects[current_id]->trans[0][0] = 1.0;
00207   vc_objects[current_id]->trans[1][1] = 1.0;
00208   vc_objects[current_id]->trans[2][2] = 1.0;
00209   vc_objects[current_id]->trans[3][3] = 1.0;
00210   
00211   return VC_OK;
00212   
00213 }
00214 
00215 int VCInternal::UpdateTrans(int id, double t[][4])
00216 {             //update the transformation matrix of the object.
00217   //check whether we are in the right state.
00218   if (state != VCstate_default)
00219     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00220 
00221 
00222   VCObject *current;
00223   
00224   if (id >= size)  //invalid id.
00225     {
00226       //cerr<<"VCInternal::update_trans - no object with id = "<<id<<"\n";
00227       return VC_ERR_INVALID_ID;
00228     }
00229   else if (vc_objects[id] == NULL)  //invalid id.
00230     {
00231       //cerr<<"VCInternal::update_trans - no object with id = "<<id<<"\n";
00232       return VC_ERR_INVALID_ID;
00233     }
00234   else
00235     {
00236       current = vc_objects[id];
00237     }
00238   
00239   //update the private copy of the transformation matrix.
00240   memcpy((void *)current->trans, (void *)t, 16*sizeof(double));
00241   
00242   //have the nbody database update itself appropriately.
00243   nbody.UpdateTrans(current->id, t);
00244 
00245   return VC_OK;
00246   
00247 }
00248 
00249 
00250 int VCInternal::ActivateObject(int id)
00251 {  //activate an object for collision detection.
00252 
00253   //check whether we are in the right state.
00254   if (state != VCstate_default)
00255     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00256   
00257   if (id >= size)  //invalid id.
00258     {
00259       //cerr<<"VCInternal::activate - no object with id = "<<id<<"\n";
00260       return VC_ERR_INVALID_ID;
00261     }
00262   else if (vc_objects[id] == NULL)  //invalid id.
00263     {
00264       //cerr<<"VCInternal::activate - no object with id = "<<id<<"\n";
00265       return VC_ERR_INVALID_ID;
00266     }
00267   else
00268     {
00269       vc_objects[id]->activation_state = 1;
00270     }
00271   return VC_OK;
00272 }
00273 
00274 int VCInternal::DeactivateObject(int id)
00275 {  //deactivate an object from collision detection.
00276 
00277   //check whether we are in the right state.
00278   if (state != VCstate_default)
00279     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00280   
00281   if (id >= size)  //invalid id.
00282     {
00283       //cerr<<"VCInternal::deactivate - no object with id = "<<id<<"\n";
00284       return VC_ERR_INVALID_ID;
00285     }
00286   else if (vc_objects[id] == NULL)  //invalid id.
00287     {
00288       //cerr<<"VCInternal::deactivate - no object with id = "<<id<<"\n";
00289       return VC_ERR_INVALID_ID;
00290     } 
00291   else
00292     {
00293       vc_objects[id]->activation_state = 0;
00294     }
00295   return VC_OK;
00296 }
00297 
00298 
00299 int VCInternal::ActivatePair(int id1, int id2)
00300 {
00301   
00302   //check whether we are in the right state.
00303   if (state != VCstate_default)
00304     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00305   
00306   if ( (id1 >= size) || (id2 >= size) )  //invalid id.
00307     {
00308       //cerr<<"VCInternal::activate_pair - invalid id for activation\n";
00309       return VC_ERR_INVALID_ID;
00310     }
00311   else if ( (vc_objects[id1] == NULL) || (vc_objects[id2] == NULL) )//invalid id.
00312     {
00313       //cerr<<"VCInternal::activate_pair - invalid id for activation\n";
00314       return VC_ERR_INVALID_ID;
00315     }
00316   else
00317     {
00318       disabled.DelPair(id1, id2);
00319       return VC_OK;
00320     }
00321 }
00322 
00323 int VCInternal::DeactivatePair(int id1, int id2)
00324 {
00325 
00326   //check whether we are in the right state.
00327   if (state != VCstate_default)
00328     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00329   
00330   if ( (id1 >= size) || (id2 >= size) )  //invalid id.
00331     {
00332       //cerr<<"VCInternal::deactivate_pair - invalid id for deactivation\n";
00333       return VC_ERR_INVALID_ID;
00334     }
00335   else if ( (vc_objects[id1] == NULL) || (vc_objects[id2] == NULL) )//invalid id.
00336     {
00337       //cerr<<"VCInternal::deactivate_pair - invalid id for deactivation\n";
00338       return VC_ERR_INVALID_ID;
00339     }
00340   else
00341     {
00342       if (id1!=id2)
00343         disabled.AddPair(id1, id2);
00344       
00345       return VC_OK;
00346     }
00347 }
00348 
00349 
00350 int VCInternal::DeleteObject(int id) //delete an object from the database.
00351 {
00352   //check whether we are in the right state.
00353   if (state != VCstate_default)
00354     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00355   
00356   
00357   if (id >= size) //invalid id.
00358     {
00359       //cerr<<"VCollide::delete_object - object with id = "<<id<<" does not exist\n";
00360       return VC_ERR_INVALID_ID;
00361     }
00362   
00363   if (vc_objects[id] == NULL) //invalid id.
00364     {
00365       //cerr<<"VCollide::delete_object - object with id = "<<id<<" does not exist\n";
00366       return VC_ERR_INVALID_ID;
00367     } 
00368   else
00369     {
00370       delete vc_objects[id]->b; //delete the RAPID box.
00371       delete vc_objects[id];    //delete the object.
00372       vc_objects[id] = NULL; 
00373       
00374       disabled.DelPairsInvolvingId(id);
00375 
00376       nbody.DeleteObject(id); //delete the object from the nbody database.
00377       return VC_OK;
00378     }
00379   
00380 }
00381 
00382 
00383 
00384 int VCInternal::Collide(void)  //perform collision detection.
00385 {
00386   //check whether we are in the right state.
00387   if (state != VCstate_default)
00388     return VC_ERR_CALL_OUT_OF_SEQUENCE;
00389   
00390   //Clear the results from earlier collision tests.
00391   report_data.Clear();
00392   
00393   //Simultaneously traverse the "overlapping_pairs" database and the 
00394   //"disabled_pairs" database and make calls to the RAPID collision
00395   //detection routine where required.
00396   int i;
00397   for (i=0; i<nbody.overlapping_pairs.size; i++)
00398     {
00399       Elem *curr_ovrlp = nbody.overlapping_pairs.arr[i];
00400       
00401       Elem *curr_disabled;
00402       if (i<disabled.size)
00403         curr_disabled = disabled.arr[i];
00404       else
00405         curr_disabled = NULL;
00406       
00407       if (curr_ovrlp != NULL)
00408         {
00409           if (vc_objects[i]->activation_state == 1)
00410             {
00411               while (curr_ovrlp != NULL)
00412                 {
00413                   while (curr_disabled != NULL)
00414                     {
00415                       if (curr_disabled->id < curr_ovrlp->id)
00416                         curr_disabled = curr_disabled->next;
00417                       else
00418                         break;
00419                     }
00420                   
00421                   if (curr_disabled != NULL)
00422                     {
00423                       if (curr_disabled->id > curr_ovrlp->id)
00424                         {
00425                           if (vc_objects[curr_ovrlp->id]->activation_state == 1)
00426                             {
00427                               //now, we need to call the RAPID collision detection routine.
00428                               
00429                               double R1[3][3], T1[3], R2[3][3], T2[3];
00430                               
00431                               //set up the rotation and translation matrices as
00432                               //required by RAPID for the first object.
00433                               R1[0][0] = vc_objects[i]->trans[0][0];
00434                               R1[0][1] = vc_objects[i]->trans[0][1];
00435                               R1[0][2] = vc_objects[i]->trans[0][2];
00436                               R1[1][0] = vc_objects[i]->trans[1][0];
00437                               R1[1][1] = vc_objects[i]->trans[1][1];
00438                               R1[1][2] = vc_objects[i]->trans[1][2];
00439                               R1[2][0] = vc_objects[i]->trans[2][0];
00440                               R1[2][1] = vc_objects[i]->trans[2][1];
00441                               R1[2][2] = vc_objects[i]->trans[2][2];
00442                               
00443                               T1[0] = vc_objects[i]->trans[0][3];
00444                               T1[1] = vc_objects[i]->trans[1][3];
00445                               T1[2] = vc_objects[i]->trans[2][3];
00446                               
00447                               //set up the rotation and translation matrices for
00448                               //the second object.
00449                               R2[0][0] = vc_objects[curr_ovrlp->id]->trans[0][0];
00450                               R2[0][1] = vc_objects[curr_ovrlp->id]->trans[0][1];
00451                               R2[0][2] = vc_objects[curr_ovrlp->id]->trans[0][2];
00452                               R2[1][0] = vc_objects[curr_ovrlp->id]->trans[1][0];
00453                               R2[1][1] = vc_objects[curr_ovrlp->id]->trans[1][1];
00454                               R2[1][2] = vc_objects[curr_ovrlp->id]->trans[1][2];
00455                               R2[2][0] = vc_objects[curr_ovrlp->id]->trans[2][0];
00456                               R2[2][1] = vc_objects[curr_ovrlp->id]->trans[2][1];
00457                               R2[2][2] = vc_objects[curr_ovrlp->id]->trans[2][2];
00458                               
00459                               T2[0] = vc_objects[curr_ovrlp->id]->trans[0][3];
00460                               T2[1] = vc_objects[curr_ovrlp->id]->trans[1][3];
00461                               T2[2] = vc_objects[curr_ovrlp->id]->trans[2][3];
00462                               
00463                               //call the RAPID collision detection routine.
00464 			      ::RAPID_Collide(R1, T1, vc_objects[i]->b, R2, T2, vc_objects[curr_ovrlp->id]->b, RAPID_FIRST_CONTACT);
00465                               
00466                               //if there is a collision, then add the pair to the
00467                               //collision report database.
00468                               if (RAPID_num_contacts != 0)
00469                                 report_data.AddPair(i, vc_objects[curr_ovrlp->id]->id);
00470                             }
00471                         }
00472                       else if (curr_disabled->id == curr_ovrlp->id)
00473                         {
00474                           curr_disabled = curr_disabled->next;
00475                         }
00476                     }
00477                   else
00478                     {
00479                       if (vc_objects[curr_ovrlp->id]->activation_state == 1)
00480                         {
00481                           //again, we need to call the RAPID collision detection routine.
00482                           
00483                           double R1[3][3], T1[3], R2[3][3], T2[3];
00484                           
00485                           //set up the rotation and translation matrices as 
00486                           //required by RAPID for the first object.
00487                           R1[0][0] = vc_objects[i]->trans[0][0];
00488                           R1[0][1] = vc_objects[i]->trans[0][1];
00489                           R1[0][2] = vc_objects[i]->trans[0][2];
00490                           R1[1][0] = vc_objects[i]->trans[1][0];
00491                           R1[1][1] = vc_objects[i]->trans[1][1];
00492                           R1[1][2] = vc_objects[i]->trans[1][2];
00493                           R1[2][0] = vc_objects[i]->trans[2][0];
00494                           R1[2][1] = vc_objects[i]->trans[2][1];
00495                           R1[2][2] = vc_objects[i]->trans[2][2];
00496                           
00497                           T1[0] = vc_objects[i]->trans[0][3];
00498                           T1[1] = vc_objects[i]->trans[1][3];
00499                           T1[2] = vc_objects[i]->trans[2][3];
00500                           
00501                           //set up the rotation and translation matrices for
00502                           //the second object.
00503                           R2[0][0] = vc_objects[curr_ovrlp->id]->trans[0][0];
00504                           R2[0][1] = vc_objects[curr_ovrlp->id]->trans[0][1];
00505                           R2[0][2] = vc_objects[curr_ovrlp->id]->trans[0][2];
00506                           R2[1][0] = vc_objects[curr_ovrlp->id]->trans[1][0];
00507                           R2[1][1] = vc_objects[curr_ovrlp->id]->trans[1][1];
00508                           R2[1][2] = vc_objects[curr_ovrlp->id]->trans[1][2];
00509                           R2[2][0] = vc_objects[curr_ovrlp->id]->trans[2][0];
00510                           R2[2][1] = vc_objects[curr_ovrlp->id]->trans[2][1];
00511                           R2[2][2] = vc_objects[curr_ovrlp->id]->trans[2][2];
00512                           
00513                           T2[0] = vc_objects[curr_ovrlp->id]->trans[0][3];
00514                           T2[1] = vc_objects[curr_ovrlp->id]->trans[1][3];
00515                           T2[2] = vc_objects[curr_ovrlp->id]->trans[2][3];
00516                           
00517                           //call the RAPID collision detection routine.
00518 			  ::RAPID_Collide(R1, T1, vc_objects[i]->b, R2, T2, vc_objects[curr_ovrlp->id]->b, RAPID_FIRST_CONTACT);
00519                           
00520                           //if there is a collision, then add the pair to the
00521                           //collision report database.
00522                           if (RAPID_num_contacts != 0)
00523                             report_data.AddPair(i, vc_objects[curr_ovrlp->id]->id);
00524                           
00525                         }
00526                     }
00527                   curr_ovrlp = curr_ovrlp->next;
00528                 }
00529             }
00530         }
00531     }
00532   return VC_OK;
00533 }
00534 
00535 
00536 //report the results of collision detection.
00537 //sz is the size of the array pointed to by vcrep. If sz is less than
00538 //the number of collision pairs, then fill the array with first sz number
00539 //of collision pairs.
00540 //Returns the total number of collision pairs.
00541 int VCInternal::Report(int sz, VCReportType *vcrep)
00542 {
00543   int no_of_colliding_pairs=0;
00544   int vc_rep_count = 0;
00545   
00546   int i;
00547   for (i=0; i<report_data.size; i++)
00548     {
00549       Elem *current;
00550       for (current=report_data.arr[i]; current != NULL; current=current->next)
00551         {
00552           no_of_colliding_pairs++;
00553           if (vc_rep_count <sz) //if the array is not full yet, then 
00554             {                   //fill the data in it.
00555               vcrep[vc_rep_count].id1 = i;
00556               vcrep[vc_rep_count].id2 = current->id;
00557               vc_rep_count++;
00558             }
00559         }
00560       
00561     }
00562   return no_of_colliding_pairs;
00563 }
00564 
00565 

Generated on Thu Dec 1 10:13:41 2005 for COME - Biomechanical Joint Model by  doxygen 1.4.5