Exemple #1
0
void PlanarPortal::teleportPointThroughPlaneB( const Vector3s& xin, Vector3s& xout ) const
{
    // Compute coordinates of x in B and invert them
    const scalar nB {
        m_portal_multiplier.x() * planeB().n().dot(  planeB().x() - xin )
    };
    const scalar tB0{ m_portal_multiplier.y() * planeB().t0().dot( planeB().x() - xin ) };
    const scalar tB1{ m_portal_multiplier.z() * planeB().t1().dot( planeB().x() - xin ) };
    // Compute the inverted coordinates in B
    xout = planeA().x() + nB * planeA().n() + tB0 * planeA().t0() + tB1 * planeA().t1();
}
Exemple #2
0
Vector2s PlanarPortal::getKinematicVelocityOfPoint( const Vector2s& x ) const
{
  assert( planeA().distanceLessThanZero( x ) != planeB().distanceLessThanZero( x ) );

  if( planeA().distanceLessThanZero( x ) )
  {
    return -m_v * m_plane_a.t();
  }
  else
  {
    return -m_v * m_plane_b.t();
  }
}
Exemple #3
0
void PlanarPortal::teleportPointThroughPlaneB( const Vector2s& xin, Vector2s& xout ) const
{
  // Compute the translated coordinates of x in B...
  const scalar nB{ planeB().n().dot( planeB().x() - xin ) };
  scalar tB{ planeB().t().dot( m_dx * m_plane_b.t() + planeB().x() - xin ) };

  // ...accounting for periodic boundaries
  const int repeat_x{ int( floor( ( tB + m_bounds ) / ( 2.0 * m_bounds ) ) ) };
  tB -= 2.0 * repeat_x * m_bounds;
  assert( tB >= -m_bounds || !isLeesEdwards() );
  assert( tB <= m_bounds || !isLeesEdwards() );

  // Map the coordinates to the corresponding plane
  xout = planeA().x() + nB * planeA().n() + tB * planeA().t();
}
Exemple #4
0
void PlanarPortal::teleportPointInsidePortal( const Vector2s& xin, Vector2s& xout ) const
{
  assert( planeA().distanceLessThanZero( xin ) != planeB().distanceLessThanZero( xin ) );

  // Teleporting form A to B
  if( planeA().distanceLessThanZero( xin ) )
  {
    teleportPointThroughPlaneA( xin, xout );
  }
  // Teleporting form B to A
  else
  {
    teleportPointThroughPlaneB( xin, xout );
  }
}
Exemple #5
0
void PlanarPortal::teleportPointInsidePortal( const Vector3s& xin, Vector3s& xout ) const
{
    // Point must be in one and only one side of the portal
    assert( ( planeA().distanceToPoint( xin ) < 0 ) != ( planeB().distanceToPoint( xin ) < 0 ) );

    // Teleporting form A to B
    if( planeA().distanceToPoint( xin ) < 0 )
    {
        teleportPointThroughPlaneA( xin, xout );
    }
    // Teleporting form B to A
    else
    {
        teleportPointThroughPlaneB( xin, xout );
    }
}
Exemple #6
0
void rayPlaneCollisionTests() {
	vxVector planeA(-5, 0, 0);
	vxVector planeB(5, 0, 0);
	vxVector planeC(5, 5, 0);

	// hit going forward
	vxRay testRay(vxVector(0, 2.5, -5), vxVector(0, 0, 1));
	assert(testRay.intersect(planeA, planeB, planeC).hit);

	// see if it hits even if the direction is backward
	vxRay infiniteHitRay(vxVector(0, 2.5, -5), vxVector(0, 0, -1));
	assert(infiniteHitRay.intersect(planeA, planeB, planeC).hit);
}
Exemple #7
0
void PlanarPortal::teleportPointThroughPlaneB( const Vector2s& xin, Vector2s& xout ) const
{
  // Compute coordinates of x in B and invert them
  const scalar nB{ planeB().n().dot( m_dx_b * m_plane_b.t() + planeB().x() - xin ) };
  scalar tB{ planeB().t().dot( m_dx_b * m_plane_b.t() + planeB().x() - xin ) };
  // Compute the inverted coordinates in B
  if( m_dx_a + tB < m_bounds_a(0) )
  {
    while( m_dx_a + tB < m_bounds_a(0) )
    {
      tB += m_bounds_a(1) - m_bounds_a(0);
    }
  }
  else if( m_dx_a + tB > m_bounds_a(1) )
  {
    while( m_dx_a + tB > m_bounds_a(1) )
    {
      tB += m_bounds_a(0) - m_bounds_a(1);
    }
  }
  assert( m_dx_a + tB >= m_bounds_a(0) ); assert( m_dx_a + tB <= m_bounds_a(1) );
  xout = m_dx_a * m_plane_a.t() + planeA().x() + nB * planeA().n() + tB * planeA().t();
}
Exemple #8
0
bool PlanarPortal::sphereTouchesPortal( const Vector3s& x, const scalar& r, bool& intersecting_plane_idx ) const
{
    const bool touches_plane_A{ planeA().distanceToPoint( x ) <= r };
    const bool touches_plane_B{ planeB().distanceToPoint( x ) <= r };
    if( touches_plane_A && touches_plane_B )
    {
        std::cerr << "Unhandled case in PlanarPortal::sphereTouchesPortal. Sphere can't touch both planes of a portal at once." << std::endl;
        std::exit( EXIT_FAILURE );
    }
    if( touches_plane_A )
    {
        intersecting_plane_idx = 0;
    }
    if( touches_plane_B )
    {
        intersecting_plane_idx = 1;
    }
    return touches_plane_A || touches_plane_B;
}
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;
}
Exemple #10
0
bool PlanarPortal::pointInsidePortal( const Vector2s& x ) const
{
  return planeA().distanceLessThanZero( x ) || planeB().distanceLessThanZero( x );
}
Exemple #11
0
bool PlanarPortal::pointInsidePortal( const Vector2s& x ) const
{
  return planeA().distanceLessThanZero( m_dx_a * m_plane_a.t(), x ) || planeB().distanceLessThanZero( m_dx_b * m_plane_b.t(), x );
}
Exemple #12
0
bool PlanarPortal::pointInsidePortal( const Vector3s& x ) const
{
    return ( planeA().distanceToPoint( x ) < 0 ) || ( planeB().distanceToPoint( x ) < 0 );
}