Ejemplo n.º 1
0
const AreaSurfaceMesh::TileSurfaceMesh::SurfaceMeshFace *
AreaSurfaceMesh::TileSurfaceMesh::FindFace(
	__in const NWN::Vector2 & pt,
	__in const PointVec & Points
	) const
/*++

Routine Description:

	This routine locates a face that contains a particular point.

Arguments:

	pt - Supplies the point to search for.

	Points - Supplies the point vector to use.

Return Value:

	Returns a pointer to the given face, else NULL should the face not be
	located.

Environment:

	User mode.

--*/
{
	for (const SurfaceMeshFace * Face = &m_Faces[ 0 ];
	     Face != &m_Faces[ m_NumFaces ];
	     Face += 1)
	{
		if (IsPointInTriangle( Face, pt, Points ))
			return Face;
	}

	return NULL;
}
// 
// 矩形与三角形是否相交。
//
// 参数1: 三角形点1。
// 
// 参数2: 三角形点2。
//
// 参数3: 三角形点3。
//
// 参数1: 矩形点1。
// 
// 参数2: 矩形点2。
//
// 参数3: 矩形点3。
//
// 参数4: 矩形点4。
//
// 返回值:1 相交, 0 不相交。
// 
bool FairyEditorFrame::Is_Rectangle_Triangle_Intersect(
										  POINT_3D triP1, 
										  POINT_3D triP2,
										  POINT_3D triP3,
										  POINT_3D recP1,
										  POINT_3D recP2,
										  POINT_3D recP3,
										  POINT_3D recP4
										  )
{

	// 先判断三角形是否在矩形内部。

	// 判断点1
	if((triP1.fx >= recP1.fx - OFFEET )&&(triP1.fx <= recP2.fx + OFFEET)&&(triP1.fz >= recP1.fz - OFFEET)&&(triP1.fz <= recP3.fz + OFFEET))
	{
		return true;
	}

	// 判断点2
    if((triP2.fx >= recP1.fx - OFFEET )&&(triP2.fx <= recP2.fx + OFFEET)&&(triP2.fz >= recP1.fz - OFFEET)&&(triP2.fz <= recP3.fz + OFFEET))
	{
		return true;
	}

	// 判断点3
	if((triP3.fx >= recP1.fx - OFFEET )&&(triP3.fx <= recP2.fx + OFFEET)&&(triP3.fz >= recP1.fz - OFFEET)&&(triP3.fz <= recP3.fz + OFFEET))
	{
		return true;
	}

	// 判断四方形的点是否在三角形内

	// 判断点1
	if(IsPointInTriangle(recP1, triP1, triP2, triP3))
	{
		return true;
	}

	// 判断点2
	if(IsPointInTriangle(recP2, triP1, triP2, triP3))
	{
		return true;
	}

	// 判断点3
	if(IsPointInTriangle(recP3, triP1, triP2, triP3))
	{
		return true;
	}

	// 判断点4
	if(IsPointInTriangle(recP4, triP1, triP2, triP3))
	{
		return true;
	}

	// 判断直线是否相交。
	if(CheckCross(recP1, recP2, triP1, triP2))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP1, recP2, triP2, triP3))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP1, recP2, triP3, triP1))
	{
		return true;
	}



	// 判断直线是否相交。
	if(CheckCross(recP2, recP3, triP1, triP2))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP2, recP3, triP2, triP3))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP2, recP3, triP3, triP1))
	{
		return true;
	}


	// 判断直线是否相交。
	if(CheckCross(recP3, recP4, triP1, triP2))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP3, recP4, triP2, triP3))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP3, recP4, triP3, triP1))
	{
		return true;
	}


	// 判断直线是否相交。
	if(CheckCross(recP4, recP1, triP1, triP2))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP4, recP1, triP2, triP3))
	{
		return true;
	}
	// 判断直线是否相交。
	if(CheckCross(recP4, recP1, triP3, triP1))
	{
		return true;
	}


	return false;
}
Ejemplo n.º 3
0
bool
AreaSurfaceMesh::GetLineSegmentFacesAndMesh(
	__in const NWN::Vector2 & Start,
	__in const NWN::Vector2 & End,
	__in_opt const TileSurfaceMesh * ExcludeSurfaceMesh,
	__in bool Walkable,
	__out const SurfaceMeshFace * * Face1,
	__out const SurfaceMeshFace * * Face2,
	__out const TileSurfaceMesh * * SurfaceMesh
	) const
/*++

Routine Description:

	Given the start and end bounding points of a line segment, which must
	reside entirely within the same tile surface mesh (although it may reside
	upon a seam), this routine returns the walk mesh faces that contain the
	start and end points, respectively.  Both faces are guaranteed to be joined
	to the same tile surface mesh, which is also returned.

	Only walkable faces are returned.

Arguments:

	Start - Supplies the first point of the line segment.  The line segment
	        must reside entirely within one tile surface mesh.

	End - Supplies the second point of the line segment.  The line segment must
	      reside entirely within one tile surface mesh.

	ExcludeSurfaceMesh - Optionally supplies a surface mesh to exclude if there
	                     should be be a tie between which surface mesh to pick
	                     for a particular triangle.  If the caller is following
	                     a line through several intersecting segments, then
	                     subsequent calls must specify the previous surface
	                     mesh in order to ensure forward progress.

	Walkable - Supplies a Boolean value indicating whether only walkable faces
	           are to be considered.

	Face1 - Receives the face containing the Start point.

	Face2 - Receives the face containing the End point.

	SurfaceMesh - Receives the tile surface mesh that both faces are joined to.

Return Value:

	Returns true two faces joined to the same tile surface mesh and containing
	the Start and End points could be located.  Otherwise, the routine returns
	false.

Environment:

	User mode.

--*/
{
	const SurfaceMeshFace * f1;
	const TileSurfaceMesh * t1;
	const SurfaceMeshFace * f2;
	const TileSurfaceMesh * t2;

	f1 = FindFace( Start, &t1 );

	if (f1 == NULL)
		return false;

	if ((Walkable) && (!(f1->Flags & SurfaceMeshFace::WALKABLE)))
		return false;

	f2 = FindFace( End, &t2 );

	if (f2 == NULL)
		return false;

	if ((Walkable) && (!(f2->Flags & SurfaceMeshFace::WALKABLE)))
		return false;

//	WriteText( "Try (%f, %f) and (%f, %f)\n", f1->Centroid2.x, f1->Centroid2.y, f2->Centroid2.x, f2->Centroid2.y );

	//
	// If the points were not in the same surface mesh then it's possible
	// that we picked the wrong one.  This may happen as it is not very
	// well defined what the behavior should be should we be right on a
	// seam between tile surface walkmesh objects.
	//
	// In the seam case, we iterate through all neighbor edges, looking for
	// the edge that matches the line.  Once we've got the edge, we'll pick
	// the two triangles that are in the same tiele surface walkmesh.
	//

	if ((t1 != t2) || (t1 == ExcludeSurfaceMesh))
	{
		const SurfaceMeshFace * faces[ 4 ];
		const SurfaceMeshEdge * e1;
		const SurfaceMeshEdge * e2;
		NWN::Vector2            v1;
		NWN::Vector2            v2;
		NWN::Vector2            I0;
		unsigned long           TestFaceId;
		bool                    Parallel;

//		WriteText( "We weren't in the same walkmesh!\n" );

		//
		// Build a list of candidate faces.  We start with the two that we've
		// originally found, but these may be on the wrong sides -- that is,
		// they might not be on the correct tile surface walkmesh.  Check the
		// other sides (if applicable); two of the faces will be on opposite
		// walkmesh tiles (i.e. the triangle we just walked through, and the
		// triangle that we'll walk through after we pass through this next
		// walkmesh.  Conversely, two of the faces will be on the correct
		// walkmesh tile -- the next walkmesh tile up.
		//

		faces[ 0 ] = f1;
		faces[ 1 ] = NULL;
		faces[ 2 ] = f2;
		faces[ 3 ] = NULL;

		for (unsigned long i = 0; i < 3; i += 1)
		{
			e1 = &GetEdges( )[ f1->Edges[ i ] ];

			//
			// Check that the edge intersects with our line segment's overlap
			// coordinate set.
			//

			v1.x = GetPoints( )[ e1->Points1 ].x;
			v1.y = GetPoints( )[ e1->Points1 ].y;
			v2.x = GetPoints( )[ e1->Points2 ].x;
			v2.y = GetPoints( )[ e1->Points2 ].y;

			if (!Math::IntersectSegments2( Start, End, v1, v2, I0, Parallel ))
			{
				e1 = NULL;
				continue;
			}

			//
			// We want the triangle on the other edge of this face.  Try it
			// too.
			//

			if (GetFaceId( f1 ) != e1->Triangles1)
				TestFaceId = e1->Triangles1;
			else
				TestFaceId = e1->Triangles2;

			if (TestFaceId == (unsigned long) -1)
				continue;

			faces[ 1 ] = &GetTriangles( )[ TestFaceId ];

			if (!IsPointInTriangle( faces[ 1 ], Start, GetPoints( ) ))
			{
				faces[ 1 ] = NULL;
				continue;
			}

			break;
		}

		for (unsigned long i = 0; i < 3; i += 1)
		{
			e2 = &GetEdges( )[ f2->Edges[ i ] ];

			//
			// Check that the edge intersects with our line segment's overlap
			// coordinate set.
			//

			v1.x = GetPoints( )[ e2->Points1 ].x;
			v1.y = GetPoints( )[ e2->Points1 ].y;
			v2.x = GetPoints( )[ e2->Points2 ].x;
			v2.y = GetPoints( )[ e2->Points2 ].y;

			if (!Math::IntersectSegments2( Start, End, v1, v2, I0, Parallel ))
			{
				e2 = NULL;
				continue;
			}

			//
			// We want the triangle on the other edge of this face.  Try it
			// too.
			//

			if (GetFaceId( f2 ) != e2->Triangles1)
				TestFaceId = e2->Triangles1;
			else
				TestFaceId = e2->Triangles2;

			if (TestFaceId == (unsigned long) -1)
				continue;

			faces[ 3 ] = &GetTriangles( )[ TestFaceId ];

			if (!IsPointInTriangle( faces[ 3 ], End, GetPoints( )))
			{
				faces[ 3 ] = NULL;
				continue;
			}

			break;
		}

//		faces[ 0 ] = e1->Triangles1 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e1->Triangles1 ];
//		faces[ 1 ] = e1->Triangles2 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e1->Triangles2 ];
//		faces[ 2 ] = e2->Triangles1 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e2->Triangles1 ];
//		faces[ 3 ] = e2->Triangles1 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e2->Triangles2 ];

		f1 = NULL;
		f2 = NULL;

		//
		// Check each triangle/edge permutation for the two that have the
		// same tile surface mesh.  These two triangles will be the ones
		// that we're looking for.
		//

		for (unsigned long i = 0; i < 2 && f1 == NULL; i += 1)
		{
			if (faces[ i + 0 ] == NULL)
				continue;

			for (unsigned long j = 0; j < 2; j += 1)
			{
				if (faces[ j + 2 ] == NULL)
					continue;

//				if ((!IsPointInTriangle( faces[ i + 0 ], Start, GetPoints( ) )) ||
//				    (!IsPointInTriangle( faces[ j + 2 ], End, GetPoints( ) )))
//					continue;

				f1 = faces[ i + 0 ];
				f2 = faces[ j + 2 ];
				t1 = &GetTileSurfaceMesh( f1 );
				t2 = &GetTileSurfaceMesh( f2 );

//				WriteText( "Try again: (%f, %f) and (%f, %f)\n", f1->Centroid2.x, f1->Centroid2.y, f2->Centroid2.x, f2->Centroid2.y );

				if ((t1 == t2) &&
				    (t1 != ExcludeSurfaceMesh))
					break;

				f1 = NULL;
				f2 = NULL;
			}
		}

		if (f1 == NULL)
		{
//			WriteText( "No triangles sharing our edge have the same TSM???\n" );
			return false;
		}
	}

//	WriteText( "%f %f %f %f\n", f1->Centroid2.x, f1->Centroid2.y, f2->Centroid2.x, f2->Centroid2.y );

	*Face1 = f1;
	*Face2 = f2;
	*SurfaceMesh = t1;

	return true;
}