bool BasicPrimitiveTests::IntersectingSegmentAgainstPlane(const LineSegment & segment, const Plane & plane, float & rtn_t)
{
	/*
		Main Idea:
            -> Subsitutes line equation into plane to find intersection
                -> Tests if intersection is within segment endpoints

        Let:
            -> Line Segment S:
                -> S(t) = A + t * (B-A)
                    -> for 0 <= t <= 1
            -> Plane P:
                -> dot(n, X) = d

        Solve for "t" of intersection:
            -> t = (    d - dot(n, A)    /    dot(n, B-A)    )

        -> Return intersection only if:
            -> 0 <= t <= 1
	*/
	
	rtn_t = (    plane.GetD() - plane.GetNormal().dot(segment.GetPointA())    )    /    plane.GetNormal().dot(segment.GetPointB() - segment.GetPointA());
	return (rtn_t <= 1.0f && rtn_t >= 0.0f);
	
}
예제 #2
0
	bool Ray::GetIntersection(const Plane &plane, float &t) const
	{
		real denom = glm::dot(plane.GetNormal(), mDirection);

		if(!denom) {
			return false;
		}

		real numer = -(glm::dot(plane.GetNormal(), mOrigin) + plane.GetD());

		t = numer / denom;

		if(t >= 0) {
			return true;
		}

		return false;
	}
예제 #3
0
파일: Ray.cpp 프로젝트: arajar/funk
	bool Ray::IntersectPlane( Plane a_plane )
	{
		v3 normal = a_plane.GetNormal();
		const float vdotn = dot( m_dir, normal );
		
        if ( fabs(vdotn) <= EPSILON )
			return false;
        
        return NewHit( - dot( m_pos - m_pos, normal ) / vdotn, normal );
	}
예제 #4
0
Vector3 PlaneEdgeIntersection(const Plane& plane, const Vector3& start, const Vector3& end)
{
	float start_dist = Vector3::Dot(start, plane.GetNormal()) + plane.GetDistance();
	float end_dist = Vector3::Dot(end, plane.GetNormal()) + plane.GetDistance();

	Vector3 ab = end - start;

	float ab_p = Vector3::Dot(plane.GetNormal(), ab);

	if (fabs(ab_p) > 0.0001f)
	{
		Vector3 p_co = plane.GetNormal() * (-plane.GetDistance());

		Vector3 w = start - p_co;
		float fac = -Vector3::Dot(plane.GetNormal(), w) / ab_p;
		ab = ab * fac;

		return start + ab;
	}

	return start;
}
예제 #5
0
파일: Ray.cpp 프로젝트: FashGek/ZED
		ZED_BOOL Ray::Intersects( const Plane &p_Plane, ZED_BOOL p_Cull,
			ZED_FLOAT32 *p_Length, Vector3 *p_HitPos )
		{
			Vector3 Normal;
			p_Plane.GetNormal( &Normal );
			ZED_FLOAT32 Dist = Normal.Dot( m_Direction );

			if( Arithmetic::IsZero( Dist ) )
			{
				return ZED_FALSE;
			}

			// Check if the plane normal is facing away from the ray's
			// direction
			if( p_Cull && ( Dist > ZED_Epsilon ) )
			{
				return ZED_FALSE;
			}

			ZED_FLOAT32 Origin = -( ( Normal.Dot( m_Origin ) ) +
				p_Plane.GetDistance( ) );

			ZED_FLOAT32 Length = Origin / Dist;

			// Intersection before ray origin
			if( Length < ( -ZED_Epsilon ) )
			{
				return ZED_FALSE;
			}

			if( p_HitPos )
			{
				( *p_HitPos ).Copy( m_Origin + ( m_Direction*Length ) );
				// As OpenGL uses a forward Z, negate it to get the correct
				// result
				( *p_HitPos )[ 2 ] = m_Origin[ 2 ]-( m_Direction[ 2 ]*Length );
				( *p_HitPos ).Clean( );
			}

			if( p_Length )
			{
				( *p_Length ) = Length;
			}

			return ZED_TRUE;
		}
예제 #6
0
파일: Ray.cpp 프로젝트: panmar/pg3
    bool Ray::Intersects(const Plane& plane, F32* distance) const {
        Vector3f planeNormal = plane.GetNormal();
        Vector3f rayEnd = origin + direction * this->distance;

        XMFLOAT4 f4PlaneCoefs(planeNormal.x, planeNormal.y, planeNormal.z, plane.GetDistance());
        XMFLOAT3 f3RayBegin(origin.v);
        XMFLOAT3 f3RayEnd(rayEnd.v);

        XMVECTOR vPlaneCoefs = XMLoadFloat4(&f4PlaneCoefs);
        XMVECTOR vRayBegin = XMLoadFloat3(&f3RayBegin); 
        XMVECTOR vRayEnd = XMLoadFloat3(&f3RayEnd);

        XMVECTOR vIntersection = XMPlaneIntersectLine(vPlaneCoefs, vRayBegin, vRayEnd);
        XMFLOAT3 f3Intersection;
        XMStoreFloat3(&f3Intersection, vIntersection);

		if (IsNaN(f3Intersection.x) || IsNaN(f3Intersection.y) || IsNaN(f3Intersection.z)) {
            return false;
        } else {
            *distance = Vector3f::Distance(origin, Vector3f(f3Intersection.x, f3Intersection.y, f3Intersection.z));
            return true;
        }
    }
예제 #7
0
void Camera::ViewportToPlaneVertex(float x, float y, IntersectionPlane p, Vector3& v) const
{
    v = Vector3::Zero;

    // unit length dir
    Vector3 dir;
    GetDirection(dir);

    // persp/ortho pos
    Vector3 pos;
    ViewportToWorldVertex(x, y, pos);

    // re-use v to be our camera normal
    ViewportToWorldNormal(x, y, v);

    // extend to clip distance
    v *= FarClipDistance;    

    // Pick ray from our starting location
    Line line = Line (pos, pos + v);

    // plane to pick against
    Plane plane = Plane::Null;

    // compute plane
    switch (p)
    {
    case IntersectionPlanes::Viewport:
        {
            switch (m_ProjectionMode)
            {
            case ProjectionModes::Perspective:
                {
                    // Planar intersections of the ray with the direction plane (camera plane)
                    plane = Plane (pos + (dir * m_Offset), dir);

                    break;
                }

            case ProjectionModes::Orthographic:
                {
                    // Planar intersections of the ray with the direction plane (camera plane)
                    plane = Plane (Vector3::Zero, dir);

                    break;
                }
            }

            break;
        }

    case IntersectionPlanes::Ground:
        {
            plane = Plane (Vector3::Zero, UpVector);
            break;
        }
    }

    plane.GetNormal(v);

    // shouldn't happen
    if (v != Vector3::Zero)
    {
        // Planar intersections of the ray with the direction plane (camera plane)
        line.IntersectsPlane(plane, &v);
    }
}
예제 #8
0
void CollisionDetection::BuildCollisionManifold(float dt, PhysicsObject* obj1, PhysicsObject* obj2, CollisionShape* shape1, CollisionShape* shape2, const CollisionData& coldata, Manifold* manifold)
{
	if (!manifold) 
		return;


	//Get the required face information for the two shapes around the collision normal
	std::list<Vector3>	 polygon1, polygon2;
	Vector3				 normal1, normal2;
	std::vector<Plane>	 adjPlanes1, adjPlanes2;

	shape1->GetIncidentReferencePolygon(obj1, coldata.normal, &polygon1, &normal1, &adjPlanes1);
	shape2->GetIncidentReferencePolygon(obj2, -coldata.normal, &polygon2, &normal2, &adjPlanes2);


	//If either shape1 or shape2 returned a single point, then it must be on a curve and thus the only contact is already availble
	if (polygon1.size() <= 1)
	{
		if (polygon1.size() == 1)
		{
			manifold->AddContact(dt, polygon1.front(), polygon1.front() - coldata.normal * coldata.penetration, coldata.normal, coldata.penetration);
		}
	}
	else if (polygon2.size() == 1)
	{
		manifold->AddContact(dt, polygon2.front() + coldata.normal * coldata.penetration, polygon2.front(), coldata.normal, coldata.penetration);
	}
	else
	{
		//Otherwise use clipping to cut down the incident face to fit inside the reference planes using the surrounding face planes

		bool				 flipped;
		std::list<Vector3>	 *incPolygon;
		Vector3				 *incNormal;
		std::vector<Plane>	 *refAdjPlanes;
		Plane				 refPlane;

		//Get the incident and reference polygons
		if (fabs(Vector3::Dot(coldata.normal, normal1)) <= fabs(Vector3::Dot(coldata.normal, normal2)))
		{
			float planeDist = -Vector3::Dot(normal1, polygon1.front());
			refPlane = Plane(normal1, planeDist);
			refAdjPlanes = &adjPlanes1;

			incPolygon = &polygon2;
			incNormal = &normal2;

			flipped = false;
		}
		else
		{
			float planeDist = -Vector3::Dot(normal2, polygon2.front());
			refPlane = Plane(normal2, planeDist);
			refAdjPlanes = &adjPlanes2;

			incPolygon = &polygon1;
			incNormal = &normal1;

			flipped = true;
		}


		//Clip the Polygon
		SutherlandHodgesonClipping(*incPolygon, *refAdjPlanes, incPolygon);


		//Now we are left with a selection of valid contact points to be used for the manifold
		Vector3 startPoint = incPolygon->back();
		for (const Vector3& endPoint : *incPolygon)
		{
			float contact_penetration;
			Vector3 globalOnA, globalOnB;

			//Calculate distance to ref plane/face
			contact_penetration = -fabs(Vector3::Dot(endPoint, refPlane.GetNormal()) + refPlane.GetDistance());
			contact_penetration = min(contact_penetration, coldata.penetration);

			if (flipped)
			{
				globalOnA = endPoint - coldata.normal * contact_penetration;
				globalOnB = endPoint;
			}
			else
			{
				globalOnA = endPoint;
				globalOnB = endPoint + coldata.normal * contact_penetration;
			}

			contact_penetration = -(fabs(contact_penetration) + fabs(coldata.penetration)) * 0.5f;

			manifold->AddContact(dt, globalOnA, globalOnB, coldata.normal, contact_penetration);

			startPoint = endPoint;
		}

	}
}
예제 #9
0
 float Vector3::GetDistanceToPlane ( const Plane & aPlane ) const
 {
     return Dot ( aPlane.GetNormal(), *this ) - aPlane.GetDistance();
 }