Exemplo n.º 1
0
   int IntersectionPoints(const Circle &circleA, const Circle &circleB, Vector2 &point1, Vector2 &point2)
   {
      const Vector2 &centreA(circleA.GetCentre());
      const Vector2 &centreB(circleB.GetCentre());
      float radiusA(circleA.GetRadius());
      float radiusB(circleB.GetRadius());

      Vector2 aToB(centreB - centreA);

      float distSq = aToB.MagnitudeSquared();

      if (distSq == 0.0f)
      {
         // circles have the same centre
         // either 0 or infinite number of intersection points
         return 0;
      }

      float dist = Sqrt(distSq);

      if (dist > radiusA + radiusB || dist < Abs(radiusA - radiusB))
      {
         // Circles are not intersecting or one is contained within the other
         return 0;
      }

      float distInv = 1.0f / dist;

      float radiusASq(radiusA * radiusA);
      float radiusBSq(radiusB * radiusB);

      float a = (radiusASq - radiusBSq + distSq) * (0.5f * distInv);
      float h = Sqrt(radiusASq - a * a);

      Vector2 aToBDir(aToB * distInv);
      Vector2 m(centreA + a * aToBDir);

      Vector2 aToBNorm(-aToBDir.y, aToBDir.x);

      if (h == 0.0f)
      {
         point1 = m;
         return 1;
      }
      else
      {
         point1 = m + h * aToBNorm;
         point2 = m - h * aToBNorm;
         return 2;
      }
   }
Exemplo n.º 2
0
void TessellateTri(
    std::vector< bspVertex_t >& outVerts,
    std::vector< triangle_t >& outIndices,
    float amount,
    float normalOffsetScale,
    const bspVertex_t& a,
    const bspVertex_t& b,
    const bspVertex_t& c
)
{
    auto LPassedC = [ &c ]( const glm::vec3& point, const glm::vec3& sig ) -> bool
    {
        return ( glm::sign( c.position - point ) != sig );
    };

    float step = 1.0f / amount;

    // Use these as a basis for when either the a or b traversal vectors
    // have passed vertex c
    glm::vec3 aSig = glm::sign( c.position - a.position );
    glm::vec3 bSig = glm::sign( c.position - b.position );

    std::unique_ptr< baryCoordSystem_t > triCoordSys( new baryCoordSystem_t( a.position, b.position, c.position ) );

    bspVertex_t bToC( ( c - b ) * step );
    bspVertex_t aToC( ( c - a ) * step );
    bspVertex_t aToBStep( ( b - a ) * step );

    std::vector< triangle_t > curStrip;

    // Points which walk along the edges
    bspVertex_t a2( a );
    bspVertex_t b2( b );

    while ( true )
    {
        if ( glm::any( glm::isnan( a2.position ) ) || glm::any( glm::isnan( b2.position ) ) )
            break;

        // If either of these are set to true, then we'll have
        // triangles which exist outside of the parent tri.
        if ( LPassedC( a2.position, aSig ) || LPassedC( b2.position, bSig ) )
            break;

        if ( a2.position == c.position || b2.position == c.position )
            break;

        // Path trace the edges of our triangle defined by vertices a2 and b2
        bspVertex_t aToB( b2 - a2 );

        float walk = 0.0f;
        float walkLength = 0.0f;
        float walkStep = glm::length( aToBStep.position ) / glm::length( aToB.position );
        float endLength = glm::length( aToB.position );

        while ( walkLength < endLength )
        {
            bspVertex_t gv1( a2 + aToB * walk );
            bspVertex_t gv2( gv1 + aToBStep );
            bspVertex_t gv3( gv1 + aToC );
            bspVertex_t gv4( gv3 + aToBStep );

            gv1.position += gv1.normal * normalOffsetScale;
            gv2.position += gv2.normal * normalOffsetScale;
            gv3.position += gv3.normal * normalOffsetScale;
            gv4.position += gv4.normal * normalOffsetScale;

            size_t numVertices;
            triangle_t t1;

            // There should be a reasonable workaround for this; maybe scale
            // the vertices or something like that.
            if ( !triCoordSys->IsInTri( gv3.position ) || !triCoordSys->IsInTri( gv2.position ) )
                goto end_iteration;

            numVertices = outVerts.size();

            gv1.color = glm::u8vec4( 255 );
            gv2.color = glm::u8vec4( 255 );
            gv3.color = glm::u8vec4( 255 );

            {
                auto v1Iter = std::find( outVerts.begin(), outVerts.end(), gv1 );
                if ( v1Iter == outVerts.end() )
                {
                    outVerts.push_back( gv1 );
                    t1.indices[ 0 ] = numVertices++;
                }
                else
                {
                    t1.indices[ 0 ] = v1Iter - outVerts.begin();
                }

                auto v2Iter = std::find( outVerts.begin(), outVerts.end(), gv2 );
                if ( v2Iter == outVerts.end() )
                {
                    outVerts.push_back( gv2 );
                    t1.indices[ 1 ] = numVertices++;
                }
                else
                {
                    t1.indices[ 1 ] = v2Iter - outVerts.begin();
                }

                auto v3Iter = std::find( outVerts.begin(), outVerts.end(), gv3 );
                if ( v3Iter == outVerts.end() )
                {
                    outVerts.push_back( gv3 );
                    t1.indices[ 2 ] = numVertices++;
                }
                else
                {
                    t1.indices[ 2 ] = v3Iter - outVerts.begin();
                }
            }

            curStrip.push_back( t1 );

            // Attempt a second triangle, providing v4
            // is within the bounds
            if ( !triCoordSys->IsInTri( gv4.position ) )
                goto end_iteration;

            {
                auto v4Iter = std::find( outVerts.begin(), outVerts.end(), gv4 );

                triangle_t t2 =
                {
                    {
                        t1.indices[ 2 ],
                        t1.indices[ 1 ],
                        0
                    }
                };

                if ( v4Iter == outVerts.end() )
                {
                    outVerts.push_back( gv4 );
                    t2.indices[ 2 ] = numVertices;
                }
                else
                {
                    t2.indices[ 2 ] = v4Iter - outVerts.begin();
                }

                curStrip.push_back( t2 );
            }

end_iteration:
            walk += walkStep;
            walkLength = glm::length( aToB.position * walk );
        }

        outIndices.insert( outIndices.end(), curStrip.begin(), curStrip.end() );
        curStrip.clear();

        a2 += aToC;
        b2 += bToC;
    }
}