static SCE_PFX_FORCE_INLINE
bool pfxContactTriangleConvex(PfxContactCache &contacts,PfxUInt32 facetId,
							const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2,
							const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2,
							PfxUInt32 edgeChk,
							const PfxConvexMesh &convex)
{
	PfxVector3 facetPnts[6] = {
		p0,p1,p2,p0-thickness*normal,p1-thickness*normal,p2-thickness*normal
	};
	

	PfxPoint3 pA(0.0f),pB(0.0f);
	PfxVector3 nml(0.0f);
	PfxGjkSolver gjk;

	gjk.setup((void*)facetPnts,(void*)&convex,pfxGetSupportVertexTriangleWithThickness,pfxGetSupportVertexConvex);
	PfxFloat d = gjk.collide(nml,pA,pB,PfxTransform3::identity(),PfxTransform3::identity(),SCE_PFX_FLT_MAX);
	if(d >= 0.0f) return false;
	
	PfxVector3 pointsOnTriangle = PfxVector3(pA);
	PfxVector3 pointsOnConvex = PfxVector3(pB);
	PfxVector3 axis = nml;
	
	// 面上の最近接点が凸エッジ上でない場合は法線を変える
	if( ((edgeChk&0x01)&&pfxPointOnLine(pointsOnTriangle,p0,p1)) ||
		((edgeChk&0x02)&&pfxPointOnLine(pointsOnTriangle,p1,p2)) ||
		((edgeChk&0x04)&&pfxPointOnLine(pointsOnTriangle,p2,p0)) ) {
		axis=-normal;
	}
	
	PfxSubData subData;
	subData.setFacetId(facetId);
	contacts.addContactPoint(-length(pointsOnTriangle-pointsOnConvex),axis,pA,pB,subData);
	
	return true;
}
static SCE_PFX_FORCE_INLINE
bool pfxContactTriangleSphere(PfxContactCache &contacts,PfxUInt32 facetId,
	const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2,
	const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2,
	PfxUInt32 edgeChk,
	PfxFloat sphereRadius,const PfxVector3 &spherePos)
{
	PfxVector3 facetPnts[3] = {
		p0,p1,p2,
	};
	
	// 早期判定
	{
		PfxPlane planeA(normal,p0);
		PfxFloat len1 = planeA.onPlane(spherePos);
		
		if(len1 >= sphereRadius || len1 < -thickness-sphereRadius) return false;
		
	}

	// 球と面の最近接点を計算
	{
		PfxTriangle triangleA(p0,p1,p2);
		PfxVector3 pntA;
		// pfxClosestPointTriangle(spherePos,triangleA,pntA);
		bool insideTriangle = false;
		while(1) {
		    PfxVector3 ab = p1 - p0;
		    PfxVector3 ac = p2 - p0;
		    PfxVector3 ap = spherePos - p0;
		    PfxFloat d1 = dot(ab, ap);
		    PfxFloat d2 = dot(ac, ap);
			if(d1 <= 0.0f && d2 <= 0.0f) {
				pntA = p0;
				break;
			}

		    PfxVector3 bp = spherePos - p1;
		    PfxFloat d3 = dot(ab, bp);
		    PfxFloat d4 = dot(ac, bp);
			if (d3 >= 0.0f && d4 <= d3) {
				pntA = p1;
				break;
			}

		    PfxFloat vc = d1*d4 - d3*d2;
		    if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
		        PfxFloat v = d1 / (d1 - d3);
		        pntA = p0 + v * ab;
				break;
		    }

		    PfxVector3 cp = spherePos - p2;
		    PfxFloat d5 = dot(ab, cp);
		    PfxFloat d6 = dot(ac, cp);
			if (d6 >= 0.0f && d5 <= d6) {
				pntA = p2;
				break;
			}

		    PfxFloat vb = d5*d2 - d1*d6;
		    if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
		        PfxFloat w = d2 / (d2 - d6);
		        pntA = p0 + w * ac;
				break;
		    }

		    PfxFloat va = d3*d6 - d5*d4;
		    if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
		        PfxFloat w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
		        pntA = p1 + w * (p2 - p1);
				break;
		    }

		    PfxFloat den = 1.0f / (va + vb + vc);
		    PfxFloat v = vb * den;
		    PfxFloat w = vc * den;
		    pntA = p0 + ab * v + ac * w;
		    insideTriangle = true;
			break;
		}
		PfxVector3 distVec = pntA - spherePos;
		PfxFloat l = length(distVec);
		
		if(!insideTriangle && l >= sphereRadius) return false;
		
		// 分離軸
		PfxVector3 sepAxis = (l < 0.00001f || insideTriangle) ? -normal : distVec / l;

		// 球上の衝突点
		PfxVector3 pointsOnSphere = spherePos + sphereRadius * sepAxis;
		PfxVector3 pointsOnTriangle = pntA;

		// 面上の最近接点が凸エッジ上でない場合は法線を変える
		if( ((edgeChk&0x01)&&pfxPointOnLine(pointsOnTriangle,p0,p1)) ||
			((edgeChk&0x02)&&pfxPointOnLine(pointsOnTriangle,p1,p2)) ||
			((edgeChk&0x04)&&pfxPointOnLine(pointsOnTriangle,p2,p0)) ) {
			sepAxis=-normal;
		}

		PfxSubData subData;
		subData.setFacetId(facetId);
		contacts.addContactPoint(-length(pointsOnSphere-pointsOnTriangle),sepAxis,PfxPoint3(pointsOnTriangle),PfxPoint3(pointsOnSphere),subData);
	}

	return true;
}