diff options
Diffstat (limited to 'thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp')
-rw-r--r-- | thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp new file mode 100644 index 0000000000..20e41de089 --- /dev/null +++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp @@ -0,0 +1,146 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_contact.h" + +#define MAX_COINCIDENT 8 + +void gim_contact_array::merge_contacts( + const gim_contact_array & contacts, bool normal_contact_average) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size()); + keycontacts.resize(contacts.size(),false); + + //fill key contacts + + GUINT i; + + for (i = 0;i<contacts.size() ;i++ ) + { + keycontacts[i].m_key = contacts[i].calc_key_contact(); + keycontacts[i].m_value = i; + } + + //sort keys + gim_heap_sort(keycontacts.pointer(),keycontacts.size(),GIM_RSORT_TOKEN_COMPARATOR()); + + // Merge contacts + + GUINT coincident_count=0; + btVector3 coincident_normals[MAX_COINCIDENT]; + + GUINT last_key = keycontacts[0].m_key; + GUINT key = 0; + + push_back(contacts[keycontacts[0].m_value]); + GIM_CONTACT * pcontact = &back(); + + + + for( i=1;i<keycontacts.size();i++) + { + key = keycontacts[i].m_key; + const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value]; + + if(last_key == key)//same points + { + //merge contact + if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON) + { + if(coincident_count<MAX_COINCIDENT) + { + coincident_normals[coincident_count] = scontact->m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &back(); + } + last_key = key; + } +} + +void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + GIM_CONTACT average_contact = contacts.back(); + + for (GUINT i=1;i<contacts.size() ;i++ ) + { + average_contact.m_point += contacts[i].m_point; + average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth; + } + + //divide + GREAL divide_average = 1.0f/((GREAL)contacts.size()); + + average_contact.m_point *= divide_average; + + average_contact.m_normal *= divide_average; + + average_contact.m_depth = average_contact.m_normal.length(); + + average_contact.m_normal /= average_contact.m_depth; + +} + |