mirror of
https://github.com/bulletphysics/bullet3
synced 2025-01-11 01:40:10 +00:00
eb23bb5c0c
Still need to verify to make sure no unwanted renaming is introduced.
451 lines
11 KiB
C++
451 lines
11 KiB
C++
/*
|
|
* SOLID - Software Library for Interference Detection
|
|
*
|
|
* Copyright (C) 2001-2003 Dtecta. All rights reserved.
|
|
*
|
|
* This library may be distributed under the terms of the Q Public License
|
|
* (QPL) as defined by Trolltech AS of Norway and appearing in the file
|
|
* LICENSE.QPL included in the packaging of this file.
|
|
*
|
|
* This library may be distributed and/or modified under the terms of the
|
|
* GNU bteral Public License (GPL) version 2 as published by the Free Software
|
|
* Foundation and appearing in the file LICENSE.GPL included in the
|
|
* packaging of this file.
|
|
*
|
|
* This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* Commercial use or any other use of this library not covered by either
|
|
* the QPL or the GPL requires an additional license from Dtecta.
|
|
* Please contact info@dtecta.com for enquiries about the terms of commercial
|
|
* use of this library.
|
|
*/
|
|
|
|
#include "Solid3JohnsonSimplexSolver.h"
|
|
#include "LinearMath/btMinMax.h"
|
|
|
|
//#define USE_BACKUP_PROCEDURE
|
|
//#define FAST_CLOSEST
|
|
|
|
Solid3JohnsonSimplexSolver::Solid3JohnsonSimplexSolver()
|
|
:
|
|
m_bits1(0x0),
|
|
m_all_bits(0x0)
|
|
{
|
|
}
|
|
|
|
|
|
Solid3JohnsonSimplexSolver::~Solid3JohnsonSimplexSolver()
|
|
{
|
|
|
|
}
|
|
|
|
void Solid3JohnsonSimplexSolver::reset()
|
|
{
|
|
m_bits1 = 0x0;
|
|
m_all_bits = 0x0;
|
|
}
|
|
|
|
|
|
|
|
void Solid3JohnsonSimplexSolver::addVertex(const btVector3& w)
|
|
{
|
|
assert(!fullSimplex());
|
|
m_last = 0;
|
|
m_last_bit = 0x1;
|
|
while (contains(m_bits1, m_last_bit))
|
|
{
|
|
++m_last;
|
|
m_last_bit <<= 1;
|
|
}
|
|
m_y[m_last] = w;
|
|
m_ylen2[m_last] = w.length2();
|
|
m_all_bits = m_bits1 | m_last_bit;
|
|
|
|
update_cache();
|
|
compute_det();
|
|
}
|
|
|
|
void Solid3JohnsonSimplexSolver::addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q)
|
|
{
|
|
addVertex(w);
|
|
m_p[m_last] = p;
|
|
m_q[m_last] = q;
|
|
}
|
|
|
|
bool Solid3JohnsonSimplexSolver::emptySimplex() const
|
|
{
|
|
return m_bits1 == 0x0;
|
|
}
|
|
|
|
bool Solid3JohnsonSimplexSolver::fullSimplex() const
|
|
{
|
|
return m_bits1 == 0xf;
|
|
}
|
|
|
|
btScalar Solid3JohnsonSimplexSolver::maxVertex()
|
|
{
|
|
return m_maxlen2;
|
|
}
|
|
|
|
bool Solid3JohnsonSimplexSolver::closest(btVector3& v)
|
|
{
|
|
#ifdef FAST_CLOSEST
|
|
T_Bits s;
|
|
for (s = m_bits1; s != 0x0; --s)
|
|
{
|
|
if (subseteq(s, m_bits1) && valid(s | m_last_bit))
|
|
{
|
|
//update bits !
|
|
m_bits1 = s | m_last_bit;
|
|
compute_vector(m_bits1, v);
|
|
return true;
|
|
}
|
|
}
|
|
if (valid(m_last_bit))
|
|
{
|
|
//update bits !
|
|
m_bits1 = m_last_bit;
|
|
m_maxlen2 = m_ylen2[m_last];
|
|
v = m_y[m_last];
|
|
return true;
|
|
}
|
|
#else
|
|
T_Bits s;
|
|
for (s = m_all_bits; s != 0x0; --s)
|
|
{
|
|
if (subseteq(s, m_all_bits) && valid(s))
|
|
{
|
|
m_bits1 = s;
|
|
compute_vector(m_bits1, v);
|
|
return true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Original GJK calls the backup procedure at this point.
|
|
#ifdef USE_BACKUP_PROCEDURE
|
|
backup_closest(btVector3& v);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
int Solid3JohnsonSimplexSolver::getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const
|
|
{
|
|
int num_verts = 0;
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(m_bits1, bit))
|
|
{
|
|
pBuf[num_verts] = m_p[i];
|
|
qBuf[num_verts] = m_q[i];
|
|
yBuf[num_verts] = m_y[i];
|
|
|
|
#ifdef DEBUG
|
|
std::cout << "Point " << i << " = " << m_y[i] << std::endl;
|
|
#endif
|
|
|
|
++num_verts;
|
|
}
|
|
}
|
|
return num_verts;
|
|
}
|
|
|
|
bool Solid3JohnsonSimplexSolver::inSimplex(const btVector3& w)
|
|
{
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(m_all_bits, bit) && w == m_y[i])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
void Solid3JohnsonSimplexSolver::backup_closest(btVector3& v)
|
|
{
|
|
btScalar min_dist2 = SIMD_INFINITY;
|
|
|
|
T_Bits s;
|
|
for (s = m_all_bits; s != 0x0; --s)
|
|
{
|
|
if (subseteq(s, m_all_bits) && proper(s))
|
|
{
|
|
btVector3 u;
|
|
compute_vector(s, u);
|
|
btScalar dist2 = u.length2();
|
|
if (dist2 < min_dist2)
|
|
{
|
|
min_dist2 = dist2;
|
|
//update bits !
|
|
m_bits1 = s;
|
|
v = u;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Solid3JohnsonSimplexSolver::compute_points(btPoint3& p1, btPoint3& p2)
|
|
{
|
|
btScalar sum = btScalar(0.0);
|
|
p1.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
|
p2.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(m_bits1, bit))
|
|
{
|
|
sum += m_det[m_bits1][i];
|
|
p1 += m_p[i] * m_det[m_bits1][i];
|
|
p2 += m_q[i] * m_det[m_bits1][i];
|
|
}
|
|
}
|
|
|
|
assert(sum > btScalar(0.0));
|
|
btScalar s = btScalar(1.0) / sum;
|
|
p1 *= s;
|
|
p2 *= s;
|
|
}
|
|
|
|
|
|
|
|
int Solid3JohnsonSimplexSolver::numVertices() const
|
|
{
|
|
int numverts = 0;
|
|
int i,bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(m_bits1, bit))
|
|
{
|
|
numverts++;
|
|
}
|
|
}
|
|
return numverts;
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////
|
|
//internal
|
|
|
|
inline void Solid3JohnsonSimplexSolver::update_cache()
|
|
{
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(m_bits1, bit))
|
|
{
|
|
m_edge[i][m_last] = m_y[i] - m_y[m_last];
|
|
m_edge[m_last][i] = -m_edge[i][m_last];
|
|
|
|
#ifdef JOHNSON_ROBUST
|
|
m_norm[i][m_last] = m_norm[m_last][i] = m_edge[i][m_last].length2();
|
|
#endif
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool Solid3JohnsonSimplexSolver::valid(T_Bits s)
|
|
{
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(m_all_bits, bit))
|
|
{
|
|
if (contains(s, bit))
|
|
{
|
|
if (m_det[s][i] <= btScalar(0.0))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (m_det[s | bit][i] > btScalar(0.0))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Solid3JohnsonSimplexSolver::proper(T_Bits s)
|
|
{
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(s, bit) && m_det[s][i] <= btScalar(0.0))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Solid3JohnsonSimplexSolver::compute_vector(T_Bits s, btVector3& v)
|
|
{
|
|
m_maxlen2 = btScalar(0.0);
|
|
btScalar sum = btScalar(0.0);
|
|
v .setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
|
|
|
int i;
|
|
T_Bits bit;
|
|
for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
|
|
{
|
|
if (contains(s, bit))
|
|
{
|
|
sum += m_det[s][i];
|
|
GEN_set_max(m_maxlen2, m_ylen2[i]);
|
|
v += m_y[i] * m_det[s][i];
|
|
}
|
|
}
|
|
|
|
assert(sum > btScalar(0.0));
|
|
|
|
v /= sum;
|
|
}
|
|
|
|
|
|
|
|
#ifdef JOHNSON_ROBUST
|
|
|
|
inline void Solid3JohnsonSimplexSolver::compute_det()
|
|
{
|
|
m_det[m_last_bit][m_last] = 1;
|
|
|
|
int i;
|
|
T_Bits si;
|
|
for (i = 0, si = 0x1; i < 4; ++i, si <<= 1)
|
|
{
|
|
if (contains(m_bits1, si))
|
|
{
|
|
T_Bits s2 = si | m_last_bit;
|
|
m_det[s2][i] = m_edge[m_last][i].dot(m_y[m_last]);
|
|
m_det[s2][m_last] = m_edge[i][m_last].dot(m_y[i]);
|
|
|
|
int j;
|
|
T_Bits sj;
|
|
for (j = 0, sj = 0x1; j < i; ++j, sj <<= 1)
|
|
{
|
|
if (contains(m_bits1, sj))
|
|
{
|
|
int k;
|
|
T_Bits s3 = sj | s2;
|
|
|
|
k = m_norm[i][j] < m_norm[m_last][j] ? i : m_last;
|
|
m_det[s3][j] = m_det[s2][i] * m_edge[k][j].dot(m_y[i]) +
|
|
m_det[s2][m_last] * m_edge[k][j].dot(m_y[m_last]);
|
|
k = m_norm[j][i] < m_norm[m_last][i] ? j : m_last;
|
|
m_det[s3][i] = m_det[sj|m_last_bit][j] * m_edge[k][i].dot(m_y[j]) +
|
|
m_det[sj|m_last_bit][m_last] * m_edge[k][i].dot(m_y[m_last]);
|
|
k = m_norm[i][m_last] < m_norm[j][m_last] ? i : j;
|
|
m_det[s3][m_last] = m_det[sj|si][j] * m_edge[k][m_last].dot(m_y[j]) +
|
|
m_det[sj|si][i] * m_edge[k][m_last].dot(m_y[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_all_bits == 0xf)
|
|
{
|
|
int k;
|
|
|
|
k = m_norm[1][0] < m_norm[2][0] ? (m_norm[1][0] < m_norm[3][0] ? 1 : 3) : (m_norm[2][0] < m_norm[3][0] ? 2 : 3);
|
|
|
|
m_det[0xf][0] = m_det[0xe][1] * m_edge[k][0].dot(m_y[1]) +
|
|
m_det[0xe][2] * m_edge[k][0].dot(m_y[2]) +
|
|
m_det[0xe][3] * m_edge[k][0].dot(m_y[3]);
|
|
|
|
k = m_norm[0][1] < m_norm[2][1] ? (m_norm[0][1] < m_norm[3][1] ? 0 : 3) : (m_norm[2][1] < m_norm[3][1] ? 2 : 3);
|
|
|
|
m_det[0xf][1] = m_det[0xd][0] * m_edge[k][1].dot(m_y[0]) +
|
|
m_det[0xd][2] * m_edge[k][1].dot(m_y[2]) +
|
|
m_det[0xd][3] * m_edge[k][1].dot(m_y[3]);
|
|
|
|
k = m_norm[0][2] < m_norm[1][2] ? (m_norm[0][2] < m_norm[3][2] ? 0 : 3) : (m_norm[1][2] < m_norm[3][2] ? 1 : 3);
|
|
|
|
m_det[0xf][2] = m_det[0xb][0] * m_edge[k][2].dot(m_y[0]) +
|
|
m_det[0xb][1] * m_edge[k][2].dot(m_y[1]) +
|
|
m_det[0xb][3] * m_edge[k][2].dot(m_y[3]);
|
|
|
|
k = m_norm[0][3] < m_norm[1][3] ? (m_norm[0][3] < m_norm[2][3] ? 0 : 2) : (m_norm[1][3] < m_norm[2][3] ? 1 : 2);
|
|
|
|
m_det[0xf][3] = m_det[0x7][0] * m_edge[k][3].dot(m_y[0]) +
|
|
m_det[0x7][1] * m_edge[k][3].dot(m_y[1]) +
|
|
m_det[0x7][2] * m_edge[k][3].dot(m_y[2]);
|
|
}
|
|
}
|
|
|
|
#else //JOHNSON_ROBUST
|
|
|
|
|
|
inline void Solid3JohnsonSimplexSolver::compute_det()
|
|
{
|
|
m_det[m_last_bit][m_last] = 1;
|
|
|
|
int i;
|
|
T_Bits si;
|
|
for (i = 0, si = 0x1; i < 4; ++i, si <<= 1)
|
|
{
|
|
if (contains(m_bits1, si))
|
|
{
|
|
T_Bits s2 = si | m_last_bit;
|
|
m_det[s2][i] = m_edge[m_last][i].dot(m_y[m_last]);
|
|
m_det[s2][m_last] = m_edge[i][m_last].dot(m_y[i]);
|
|
|
|
int j;
|
|
T_Bits sj;
|
|
for (j = 0, sj = 0x1; j < i; ++j, sj <<= 1)
|
|
{
|
|
if (contains(m_bits1, sj))
|
|
{
|
|
T_Bits s3 = sj | s2;
|
|
m_det[s3][j] = m_det[s2][i] * m_edge[i][j].dot(m_y[i]) +
|
|
m_det[s2][m_last] * m_edge[i][j].dot(m_y[m_last]);
|
|
m_det[s3][i] = m_det[sj|m_last_bit][j] * m_edge[j][i].dot(m_y[j]) +
|
|
m_det[sj|m_last_bit][m_last] * m_edge[j][i].dot(m_y[m_last]);
|
|
m_det[s3][m_last] = m_det[sj|si][j] * m_edge[j][m_last].dot(m_y[j]) +
|
|
m_det[sj|si][i] * m_edge[j][m_last].dot(m_y[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_all_bits == 0xf)
|
|
{
|
|
m_det[0xf][0] = m_det[0xe][1] * m_edge[1][0].dot(m_y[1]) +
|
|
m_det[0xe][2] * m_edge[1][0].dot(m_y[2]) +
|
|
m_det[0xe][3] * m_edge[1][0].dot(m_y[3]);
|
|
m_det[0xf][1] = m_det[0xd][0] * m_edge[0][1].dot(m_y[0]) +
|
|
m_det[0xd][2] * m_edge[0][1].dot(m_y[2]) +
|
|
m_det[0xd][3] * m_edge[0][1].dot(m_y[3]);
|
|
m_det[0xf][2] = m_det[0xb][0] * m_edge[0][2].dot(m_y[0]) +
|
|
m_det[0xb][1] * m_edge[0][2].dot(m_y[1]) +
|
|
m_det[0xb][3] * m_edge[0][2].dot(m_y[3]);
|
|
m_det[0xf][3] = m_det[0x7][0] * m_edge[0][3].dot(m_y[0]) +
|
|
m_det[0x7][1] * m_edge[0][3].dot(m_y[1]) +
|
|
m_det[0x7][2] * m_edge[0][3].dot(m_y[2]);
|
|
}
|
|
}
|
|
|
|
|
|
#endif //JOHNSON_ROBUST
|