Home | History | Annotate | Download | only in NarrowPhaseCollision
      1 
      2 /*
      3 Bullet Continuous Collision Detection and Physics Library
      4 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
      5 
      6 This software is provided 'as-is', without any express or implied warranty.
      7 In no event will the authors be held liable for any damages arising from the use of this software.
      8 Permission is granted to anyone to use this software for any purpose,
      9 including commercial applications, and to alter it and redistribute it freely,
     10 subject to the following restrictions:
     11 
     12 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.
     13 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
     14 3. This notice may not be removed or altered from any source distribution.
     15 
     16 	Elsevier CDROM license agreements grants nonexclusive license to use the software
     17 	for any purpose, commercial or non-commercial as long as the following credit is included
     18 	identifying the original source of the software:
     19 
     20 	Parts of the source are "from the book Real-Time Collision Detection by
     21 	Christer Ericson, published by Morgan Kaufmann Publishers,
     22 	(c) 2005 Elsevier Inc."
     23 
     24 */
     25 
     26 
     27 #include "btVoronoiSimplexSolver.h"
     28 
     29 #define VERTA  0
     30 #define VERTB  1
     31 #define VERTC  2
     32 #define VERTD  3
     33 
     34 #define CATCH_DEGENERATE_TETRAHEDRON 1
     35 void	btVoronoiSimplexSolver::removeVertex(int index)
     36 {
     37 
     38 	btAssert(m_numVertices>0);
     39 	m_numVertices--;
     40 	m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
     41 	m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
     42 	m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
     43 }
     44 
     45 void	btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
     46 {
     47 	if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
     48 		removeVertex(3);
     49 
     50 	if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
     51 		removeVertex(2);
     52 
     53 	if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
     54 		removeVertex(1);
     55 
     56 	if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
     57 		removeVertex(0);
     58 
     59 }
     60 
     61 
     62 
     63 
     64 
     65 //clear the simplex, remove all the vertices
     66 void btVoronoiSimplexSolver::reset()
     67 {
     68 	m_cachedValidClosest = false;
     69 	m_numVertices = 0;
     70 	m_needsUpdate = true;
     71 	m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
     72 	m_cachedBC.reset();
     73 }
     74 
     75 
     76 
     77 	//add a vertex
     78 void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
     79 {
     80 	m_lastW = w;
     81 	m_needsUpdate = true;
     82 
     83 	m_simplexVectorW[m_numVertices] = w;
     84 	m_simplexPointsP[m_numVertices] = p;
     85 	m_simplexPointsQ[m_numVertices] = q;
     86 
     87 	m_numVertices++;
     88 }
     89 
     90 bool	btVoronoiSimplexSolver::updateClosestVectorAndPoints()
     91 {
     92 
     93 	if (m_needsUpdate)
     94 	{
     95 		m_cachedBC.reset();
     96 
     97 		m_needsUpdate = false;
     98 
     99 		switch (numVertices())
    100 		{
    101 		case 0:
    102 				m_cachedValidClosest = false;
    103 				break;
    104 		case 1:
    105 			{
    106 				m_cachedP1 = m_simplexPointsP[0];
    107 				m_cachedP2 = m_simplexPointsQ[0];
    108 				m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
    109 				m_cachedBC.reset();
    110 				m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.));
    111 				m_cachedValidClosest = m_cachedBC.isValid();
    112 				break;
    113 			};
    114 		case 2:
    115 			{
    116 			//closest point origin from line segment
    117 					const btVector3& from = m_simplexVectorW[0];
    118 					const btVector3& to = m_simplexVectorW[1];
    119 					btVector3 nearest;
    120 
    121 					btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
    122 					btVector3 diff = p - from;
    123 					btVector3 v = to - from;
    124 					btScalar t = v.dot(diff);
    125 
    126 					if (t > 0) {
    127 						btScalar dotVV = v.dot(v);
    128 						if (t < dotVV) {
    129 							t /= dotVV;
    130 							diff -= t*v;
    131 							m_cachedBC.m_usedVertices.usedVertexA = true;
    132 							m_cachedBC.m_usedVertices.usedVertexB = true;
    133 						} else {
    134 							t = 1;
    135 							diff -= v;
    136 							//reduce to 1 point
    137 							m_cachedBC.m_usedVertices.usedVertexB = true;
    138 						}
    139 					} else
    140 					{
    141 						t = 0;
    142 						//reduce to 1 point
    143 						m_cachedBC.m_usedVertices.usedVertexA = true;
    144 					}
    145 					m_cachedBC.setBarycentricCoordinates(1-t,t);
    146 					nearest = from + t*v;
    147 
    148 					m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
    149 					m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
    150 					m_cachedV = m_cachedP1 - m_cachedP2;
    151 
    152 					reduceVertices(m_cachedBC.m_usedVertices);
    153 
    154 					m_cachedValidClosest = m_cachedBC.isValid();
    155 					break;
    156 			}
    157 		case 3:
    158 			{
    159 				//closest point origin from triangle
    160 				btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
    161 
    162 				const btVector3& a = m_simplexVectorW[0];
    163 				const btVector3& b = m_simplexVectorW[1];
    164 				const btVector3& c = m_simplexVectorW[2];
    165 
    166 				closestPtPointTriangle(p,a,b,c,m_cachedBC);
    167 				m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
    168 				m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
    169 				m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
    170 
    171 				m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
    172 				m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
    173 				m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
    174 
    175 				m_cachedV = m_cachedP1-m_cachedP2;
    176 
    177 				reduceVertices (m_cachedBC.m_usedVertices);
    178 				m_cachedValidClosest = m_cachedBC.isValid();
    179 
    180 				break;
    181 			}
    182 		case 4:
    183 			{
    184 
    185 
    186 				btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
    187 
    188 				const btVector3& a = m_simplexVectorW[0];
    189 				const btVector3& b = m_simplexVectorW[1];
    190 				const btVector3& c = m_simplexVectorW[2];
    191 				const btVector3& d = m_simplexVectorW[3];
    192 
    193 				bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
    194 
    195 				if (hasSeperation)
    196 				{
    197 
    198 					m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
    199 						m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
    200 						m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
    201 						m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
    202 
    203 					m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
    204 						m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
    205 						m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
    206 						m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
    207 
    208 					m_cachedV = m_cachedP1-m_cachedP2;
    209 					reduceVertices (m_cachedBC.m_usedVertices);
    210 				} else
    211 				{
    212 //					printf("sub distance got penetration\n");
    213 
    214 					if (m_cachedBC.m_degenerate)
    215 					{
    216 						m_cachedValidClosest = false;
    217 					} else
    218 					{
    219 						m_cachedValidClosest = true;
    220 						//degenerate case == false, penetration = true + zero
    221 						m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
    222 					}
    223 					break;
    224 				}
    225 
    226 				m_cachedValidClosest = m_cachedBC.isValid();
    227 
    228 				//closest point origin from tetrahedron
    229 				break;
    230 			}
    231 		default:
    232 			{
    233 				m_cachedValidClosest = false;
    234 			}
    235 		};
    236 	}
    237 
    238 	return m_cachedValidClosest;
    239 
    240 }
    241 
    242 //return/calculate the closest vertex
    243 bool btVoronoiSimplexSolver::closest(btVector3& v)
    244 {
    245 	bool succes = updateClosestVectorAndPoints();
    246 	v = m_cachedV;
    247 	return succes;
    248 }
    249 
    250 
    251 
    252 btScalar btVoronoiSimplexSolver::maxVertex()
    253 {
    254 	int i, numverts = numVertices();
    255 	btScalar maxV = btScalar(0.);
    256 	for (i=0;i<numverts;i++)
    257 	{
    258 		btScalar curLen2 = m_simplexVectorW[i].length2();
    259 		if (maxV < curLen2)
    260 			maxV = curLen2;
    261 	}
    262 	return maxV;
    263 }
    264 
    265 
    266 
    267 	//return the current simplex
    268 int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const
    269 {
    270 	int i;
    271 	for (i=0;i<numVertices();i++)
    272 	{
    273 		yBuf[i] = m_simplexVectorW[i];
    274 		pBuf[i] = m_simplexPointsP[i];
    275 		qBuf[i] = m_simplexPointsQ[i];
    276 	}
    277 	return numVertices();
    278 }
    279 
    280 
    281 
    282 
    283 bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
    284 {
    285 	bool found = false;
    286 	int i, numverts = numVertices();
    287 	//btScalar maxV = btScalar(0.);
    288 
    289 	//w is in the current (reduced) simplex
    290 	for (i=0;i<numverts;i++)
    291 	{
    292 #ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
    293 		if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
    294 #else
    295 		if (m_simplexVectorW[i] == w)
    296 #endif
    297 			found = true;
    298 	}
    299 
    300 	//check in case lastW is already removed
    301 	if (w == m_lastW)
    302 		return true;
    303 
    304 	return found;
    305 }
    306 
    307 void btVoronoiSimplexSolver::backup_closest(btVector3& v)
    308 {
    309 	v = m_cachedV;
    310 }
    311 
    312 
    313 bool btVoronoiSimplexSolver::emptySimplex() const
    314 {
    315 	return (numVertices() == 0);
    316 
    317 }
    318 
    319 void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
    320 {
    321 	updateClosestVectorAndPoints();
    322 	p1 = m_cachedP1;
    323 	p2 = m_cachedP2;
    324 
    325 }
    326 
    327 
    328 
    329 
    330 bool	btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result)
    331 {
    332 	result.m_usedVertices.reset();
    333 
    334     // Check if P in vertex region outside A
    335     btVector3 ab = b - a;
    336     btVector3 ac = c - a;
    337     btVector3 ap = p - a;
    338     btScalar d1 = ab.dot(ap);
    339     btScalar d2 = ac.dot(ap);
    340     if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
    341 	{
    342 		result.m_closestPointOnSimplex = a;
    343 		result.m_usedVertices.usedVertexA = true;
    344 		result.setBarycentricCoordinates(1,0,0);
    345 		return true;// a; // barycentric coordinates (1,0,0)
    346 	}
    347 
    348     // Check if P in vertex region outside B
    349     btVector3 bp = p - b;
    350     btScalar d3 = ab.dot(bp);
    351     btScalar d4 = ac.dot(bp);
    352     if (d3 >= btScalar(0.0) && d4 <= d3)
    353 	{
    354 		result.m_closestPointOnSimplex = b;
    355 		result.m_usedVertices.usedVertexB = true;
    356 		result.setBarycentricCoordinates(0,1,0);
    357 
    358 		return true; // b; // barycentric coordinates (0,1,0)
    359 	}
    360     // Check if P in edge region of AB, if so return projection of P onto AB
    361     btScalar vc = d1*d4 - d3*d2;
    362     if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) {
    363         btScalar v = d1 / (d1 - d3);
    364 		result.m_closestPointOnSimplex = a + v * ab;
    365 		result.m_usedVertices.usedVertexA = true;
    366 		result.m_usedVertices.usedVertexB = true;
    367 		result.setBarycentricCoordinates(1-v,v,0);
    368 		return true;
    369         //return a + v * ab; // barycentric coordinates (1-v,v,0)
    370     }
    371 
    372     // Check if P in vertex region outside C
    373     btVector3 cp = p - c;
    374     btScalar d5 = ab.dot(cp);
    375     btScalar d6 = ac.dot(cp);
    376     if (d6 >= btScalar(0.0) && d5 <= d6)
    377 	{
    378 		result.m_closestPointOnSimplex = c;
    379 		result.m_usedVertices.usedVertexC = true;
    380 		result.setBarycentricCoordinates(0,0,1);
    381 		return true;//c; // barycentric coordinates (0,0,1)
    382 	}
    383 
    384     // Check if P in edge region of AC, if so return projection of P onto AC
    385     btScalar vb = d5*d2 - d1*d6;
    386     if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) {
    387         btScalar w = d2 / (d2 - d6);
    388 		result.m_closestPointOnSimplex = a + w * ac;
    389 		result.m_usedVertices.usedVertexA = true;
    390 		result.m_usedVertices.usedVertexC = true;
    391 		result.setBarycentricCoordinates(1-w,0,w);
    392 		return true;
    393         //return a + w * ac; // barycentric coordinates (1-w,0,w)
    394     }
    395 
    396     // Check if P in edge region of BC, if so return projection of P onto BC
    397     btScalar va = d3*d6 - d5*d4;
    398     if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) {
    399         btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
    400 
    401 		result.m_closestPointOnSimplex = b + w * (c - b);
    402 		result.m_usedVertices.usedVertexB = true;
    403 		result.m_usedVertices.usedVertexC = true;
    404 		result.setBarycentricCoordinates(0,1-w,w);
    405 		return true;
    406        // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
    407     }
    408 
    409     // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
    410     btScalar denom = btScalar(1.0) / (va + vb + vc);
    411     btScalar v = vb * denom;
    412     btScalar w = vc * denom;
    413 
    414 	result.m_closestPointOnSimplex = a + ab * v + ac * w;
    415 	result.m_usedVertices.usedVertexA = true;
    416 	result.m_usedVertices.usedVertexB = true;
    417 	result.m_usedVertices.usedVertexC = true;
    418 	result.setBarycentricCoordinates(1-v-w,v,w);
    419 
    420 	return true;
    421 //	return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
    422 
    423 }
    424 
    425 
    426 
    427 
    428 
    429 /// Test if point p and d lie on opposite sides of plane through abc
    430 int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
    431 {
    432 	btVector3 normal = (b-a).cross(c-a);
    433 
    434     btScalar signp = (p - a).dot(normal); // [AP AB AC]
    435     btScalar signd = (d - a).dot( normal); // [AD AB AC]
    436 
    437 #ifdef CATCH_DEGENERATE_TETRAHEDRON
    438 #ifdef BT_USE_DOUBLE_PRECISION
    439 if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
    440 	{
    441 		return -1;
    442 	}
    443 #else
    444 	if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
    445 	{
    446 //		printf("affine dependent/degenerate\n");//
    447 		return -1;
    448 	}
    449 #endif
    450 
    451 #endif
    452 	// Points on opposite sides if expression signs are opposite
    453     return signp * signd < btScalar(0.);
    454 }
    455 
    456 
    457 bool	btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
    458 {
    459 	btSubSimplexClosestResult tempResult;
    460 
    461     // Start out assuming point inside all halfspaces, so closest to itself
    462 	finalResult.m_closestPointOnSimplex = p;
    463 	finalResult.m_usedVertices.reset();
    464     finalResult.m_usedVertices.usedVertexA = true;
    465 	finalResult.m_usedVertices.usedVertexB = true;
    466 	finalResult.m_usedVertices.usedVertexC = true;
    467 	finalResult.m_usedVertices.usedVertexD = true;
    468 
    469     int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
    470 	int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
    471   	int	pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
    472 	int	pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
    473 
    474    if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
    475    {
    476 	   finalResult.m_degenerate = true;
    477 	   return false;
    478    }
    479 
    480    if (!pointOutsideABC  && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
    481 	 {
    482 		 return false;
    483 	 }
    484 
    485 
    486     btScalar bestSqDist = FLT_MAX;
    487     // If point outside face abc then compute closest point on abc
    488 	if (pointOutsideABC)
    489 	{
    490         closestPtPointTriangle(p, a, b, c,tempResult);
    491 		btVector3 q = tempResult.m_closestPointOnSimplex;
    492 
    493         btScalar sqDist = (q - p).dot( q - p);
    494         // Update best closest point if (squared) distance is less than current best
    495         if (sqDist < bestSqDist) {
    496 			bestSqDist = sqDist;
    497 			finalResult.m_closestPointOnSimplex = q;
    498 			//convert result bitmask!
    499 			finalResult.m_usedVertices.reset();
    500 			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
    501 			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
    502 			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
    503 			finalResult.setBarycentricCoordinates(
    504 					tempResult.m_barycentricCoords[VERTA],
    505 					tempResult.m_barycentricCoords[VERTB],
    506 					tempResult.m_barycentricCoords[VERTC],
    507 					0
    508 			);
    509 
    510 		}
    511     }
    512 
    513 
    514 	// Repeat test for face acd
    515 	if (pointOutsideACD)
    516 	{
    517         closestPtPointTriangle(p, a, c, d,tempResult);
    518 		btVector3 q = tempResult.m_closestPointOnSimplex;
    519 		//convert result bitmask!
    520 
    521         btScalar sqDist = (q - p).dot( q - p);
    522         if (sqDist < bestSqDist)
    523 		{
    524 			bestSqDist = sqDist;
    525 			finalResult.m_closestPointOnSimplex = q;
    526 			finalResult.m_usedVertices.reset();
    527 			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
    528 
    529 			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
    530 			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
    531 			finalResult.setBarycentricCoordinates(
    532 					tempResult.m_barycentricCoords[VERTA],
    533 					0,
    534 					tempResult.m_barycentricCoords[VERTB],
    535 					tempResult.m_barycentricCoords[VERTC]
    536 			);
    537 
    538 		}
    539     }
    540     // Repeat test for face adb
    541 
    542 
    543 	if (pointOutsideADB)
    544 	{
    545 		closestPtPointTriangle(p, a, d, b,tempResult);
    546 		btVector3 q = tempResult.m_closestPointOnSimplex;
    547 		//convert result bitmask!
    548 
    549         btScalar sqDist = (q - p).dot( q - p);
    550         if (sqDist < bestSqDist)
    551 		{
    552 			bestSqDist = sqDist;
    553 			finalResult.m_closestPointOnSimplex = q;
    554 			finalResult.m_usedVertices.reset();
    555 			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
    556 			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
    557 
    558 			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
    559 			finalResult.setBarycentricCoordinates(
    560 					tempResult.m_barycentricCoords[VERTA],
    561 					tempResult.m_barycentricCoords[VERTC],
    562 					0,
    563 					tempResult.m_barycentricCoords[VERTB]
    564 			);
    565 
    566 		}
    567     }
    568     // Repeat test for face bdc
    569 
    570 
    571 	if (pointOutsideBDC)
    572 	{
    573         closestPtPointTriangle(p, b, d, c,tempResult);
    574 		btVector3 q = tempResult.m_closestPointOnSimplex;
    575 		//convert result bitmask!
    576         btScalar sqDist = (q - p).dot( q - p);
    577         if (sqDist < bestSqDist)
    578 		{
    579 			bestSqDist = sqDist;
    580 			finalResult.m_closestPointOnSimplex = q;
    581 			finalResult.m_usedVertices.reset();
    582 			//
    583 			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
    584 			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
    585 			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
    586 
    587 			finalResult.setBarycentricCoordinates(
    588 					0,
    589 					tempResult.m_barycentricCoords[VERTA],
    590 					tempResult.m_barycentricCoords[VERTC],
    591 					tempResult.m_barycentricCoords[VERTB]
    592 			);
    593 
    594 		}
    595     }
    596 
    597 	//help! we ended up full !
    598 
    599 	if (finalResult.m_usedVertices.usedVertexA &&
    600 		finalResult.m_usedVertices.usedVertexB &&
    601 		finalResult.m_usedVertices.usedVertexC &&
    602 		finalResult.m_usedVertices.usedVertexD)
    603 	{
    604 		return true;
    605 	}
    606 
    607     return true;
    608 }
    609 
    610