Blender V2.61 - r43446

btContactProcessing.cpp

Go to the documentation of this file.
00001 
00002 /*
00003 This source file is part of GIMPACT Library.
00004 
00005 For the latest info, see http://gimpact.sourceforge.net/
00006 
00007 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
00008 email: projectileman@yahoo.com
00009 
00010 
00011 This software is provided 'as-is', without any express or implied warranty.
00012 In no event will the authors be held liable for any damages arising from the use of this software.
00013 Permission is granted to anyone to use this software for any purpose,
00014 including commercial applications, and to alter it and redistribute it freely,
00015 subject to the following restrictions:
00016 
00017 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00018 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00019 3. This notice may not be removed or altered from any source distribution.
00020 */
00021 #include "btContactProcessing.h"
00022 
00023 #define MAX_COINCIDENT 8
00024 
00025 struct CONTACT_KEY_TOKEN
00026 {
00027     unsigned int m_key;
00028     int m_value;
00029     CONTACT_KEY_TOKEN()
00030     {
00031     }
00032 
00033     CONTACT_KEY_TOKEN(unsigned int key,int token)
00034     {
00035         m_key = key;
00036         m_value =  token;
00037     }
00038 
00039     CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
00040     {
00041         m_key = rtoken.m_key;
00042         m_value = rtoken.m_value;
00043     }
00044 
00045     inline bool operator <(const CONTACT_KEY_TOKEN& other) const
00046     {
00047         return (m_key < other.m_key);
00048     }
00049 
00050     inline bool operator >(const CONTACT_KEY_TOKEN& other) const
00051     {
00052         return (m_key > other.m_key);
00053     }
00054 
00055 };
00056 
00057 class CONTACT_KEY_TOKEN_COMP
00058 {
00059     public:
00060 
00061         bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b )
00062         {
00063             return ( a < b );
00064         }
00065 };
00066 
00067 
00068 void btContactArray::merge_contacts(
00069     const btContactArray & contacts, bool normal_contact_average)
00070 {
00071     clear();
00072 
00073     int i;
00074     if(contacts.size()==0) return;
00075 
00076 
00077     if(contacts.size()==1)
00078     {
00079         push_back(contacts[0]);
00080         return;
00081     }
00082 
00083     btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
00084 
00085     keycontacts.reserve(contacts.size());
00086 
00087     //fill key contacts
00088 
00089     for ( i = 0;i<contacts.size() ;i++ )
00090     {
00091         keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
00092     }
00093 
00094     //sort keys
00095     keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
00096 
00097     // Merge contacts
00098     int coincident_count=0;
00099     btVector3 coincident_normals[MAX_COINCIDENT];
00100 
00101     unsigned int last_key = keycontacts[0].m_key;
00102     unsigned int key = 0;
00103 
00104     push_back(contacts[keycontacts[0].m_value]);
00105 
00106     GIM_CONTACT * pcontact = &(*this)[0];
00107 
00108     for( i=1;i<keycontacts.size();i++)
00109     {
00110         key = keycontacts[i].m_key;
00111         const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
00112 
00113         if(last_key ==  key)//same points
00114         {
00115             //merge contact
00116             if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
00117             {
00118                 *pcontact = *scontact;
00119                 coincident_count = 0;
00120             }
00121             else if(normal_contact_average)
00122             {
00123                 if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
00124                 {
00125                     if(coincident_count<MAX_COINCIDENT)
00126                     {
00127                         coincident_normals[coincident_count] = scontact->m_normal;
00128                         coincident_count++;
00129                     }
00130                 }
00131             }
00132         }
00133         else
00134         {//add new contact
00135 
00136             if(normal_contact_average && coincident_count>0)
00137             {
00138                 pcontact->interpolate_normals(coincident_normals,coincident_count);
00139                 coincident_count = 0;
00140             }
00141 
00142             push_back(*scontact);
00143             pcontact = &(*this)[this->size()-1];
00144         }
00145         last_key = key;
00146     }
00147 }
00148 
00149 void btContactArray::merge_contacts_unique(const btContactArray & contacts)
00150 {
00151     clear();
00152 
00153     if(contacts.size()==0) return;
00154 
00155     if(contacts.size()==1)
00156     {
00157         push_back(contacts[0]);
00158         return;
00159     }
00160 
00161     GIM_CONTACT average_contact = contacts[0];
00162 
00163     for (int i=1;i<contacts.size() ;i++ )
00164     {
00165         average_contact.m_point += contacts[i].m_point;
00166         average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
00167     }
00168 
00169     //divide
00170     btScalar divide_average = 1.0f/((btScalar)contacts.size());
00171 
00172     average_contact.m_point *= divide_average;
00173 
00174     average_contact.m_normal *= divide_average;
00175 
00176     average_contact.m_depth = average_contact.m_normal.length();
00177 
00178     average_contact.m_normal /= average_contact.m_depth;
00179 
00180 }
00181