A Game Programming Math Question: Projecting Point to Plane

Dear Community & Friends at Epic,

Because I working on an editor mode I cant use the UCanvas projection function, and the FCanvas versions for getting a matrix are currently not exposed to Rocket Users.

So I need to get a plane and do the projection myself.

but I do not understand the math involved :slight_smile:

#The Plane

I have a UE4 plane:

UPROPERTY()
FPlane ClickPlane;

#The Point

I have a 3D point to project onto this plane (the plane of the editor’s canvas)

FVector Point (Actor's location for example)

How do I use one of these two functions to project the 3d point onto the click plane?

The Functions

Vector.h

/**
	 * Calculate a the projection of a point on the plane defined by CCW points A,B,C
	 *
	 * @param Point - the point to project onto the plane
	 * @param A,B,C - three points in CCW order defining the plane 
	 *
	 * @return Projection of Point onto plane ABC
	 */
	static FVector PointPlaneProject(const FVector& Point, const FVector& A, const FVector& B, const FVector& C);

	/**
	* Calculate a the projection of a point on the plane defined by PlaneBase, and PlaneNormal
	*
	* @param Point - the point to project onto the plane
	* @param PlaneBase - point on the plane
	* @param PlaneNorm - normal of the plane
	*
	* @return Projection of Point onto plane ABC
	*/
	static FVector PointPlaneProject(const FVector& Point, const FVector& PlaneBase, const FVector& PlaneNorm);

#What is a Plane’s Base Point and Normal?

I dont understand how to calculate the base point and normal of a plane :slight_smile:

For your Reference:

Plane.h

// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.

#pragma once

/**
 * FPlane.
 * Stores the coeffecients as Ax+By+Cz=D.
 * Note that this is different than many other Plane classes that use Ax+By+Cz+D=0.
 */
MS_ALIGN(16) class FPlane : public FVector
{
public:
	// Variables.
	float W;

	/** Constructor.*/
	FORCEINLINE FPlane();

	/**
	 * Copy Constructor.
	 *
	 * @param P Plane to copy from.
	 */
	FORCEINLINE FPlane( const FPlane& P );

	/**
	 * Constructor.
	 *
	 * @param V 4D vector to set up plane.
	 */
	FORCEINLINE FPlane( const FVector4& V );

	/**
	 * Constructor.
	 *
	 * @param InX X Coordinate.
	 * @param InY Y Coordinate.
	 * @param InZ Z Coordinate.
	 * @param InW W Coordinate.
	 */
	FORCEINLINE FPlane( float InX, float InY, float InZ, float InW );

	/**
	 * Constructor.
	 *
	 * @param InNormal Plane Normal Vector.
	 * @param InW Plane W Coordinate.
	 */
	FORCEINLINE FPlane( FVector InNormal, float InW );

	/**
	 * Constructor.
	 *
	 * @param InBase Base point in plane.
	 * @param InNormal Plane Normal Vector.
	 */
	FORCEINLINE FPlane( FVector InBase, const FVector &InNormal );

	/**
	 * Constructor.
	 *
	 * @param A First point in the plane.
	 * @param B Second point in the plane.
	 * @param C Third point in the plane.
	 */
	FPlane( FVector A, FVector B, FVector C );

	/**
	 * Constructor
	 *
	 * @param EForceInit Force Init Enum.
	 */
	explicit FORCEINLINE FPlane(EForceInit);

	// Functions.

	/**
	 * Calculates distance between plane and a point.
	 *
	 * @param P The other point.
	 *
	 * @return >0: point is in front of the plane, <0: behind, =0: on the plane */
	FORCEINLINE float PlaneDot( const FVector &P ) const;

A mathematical representation of a plane can be defined in two ways (or more, but these are the ones I often use). You can either use three vector points or a vector point paired with a vector normal.

Three vector points define the “surface” of a plane by actually representing the a polygon of a plane. Direction of the plane can be defined by figuring out if the vectors are clock wise or anti clockwise. If you look at the image above, it would be the vectors a, b and c.

The other method which is more common as it requires fewer vectors. It requires a point somewhere on the plane and the normal which is the direction at which the plane is facing. If you look at the image above, it would be vector a or b or c and the plane normal would be the purple line.

Just remember that a plane in mathematical terms represents an infinite surface.

I’m not 100% sure what you’re trying to do however. Are you trying to find the intersection point between a ray and the surface?

Thanks for the help James!

De Projection

I am just trying to implement the Deproject() function from UCanvas.

I cannot use UCanvas in my FEdMode DrawHUD function, because it uses FCanvas


and I cannot use the FCanvas deproject functions because they are not exposed to rocket users.


so I need to use the ClickPlane() as the editor HUD plane,

and then use a 3D Vector point in space

to then deproject the 2D coordinates on the Editor’s FCanvas

so I can represent the 3D verticies of a static mesh

as 2D squares drawn to the FCanvas :slight_smile:

Thanks!

Rama

Never mind,

I found all the functions I could ever want in SceneManagement.h

and the FSceneView ptr

yay!

/** 
	 * Transforms a point from the view's world-space into the view's screen-space. 
	 * Divides the resulting X, Y, Z by W before returning. 
	 */
	FPlane Project(const FVector& WorldPoint) const;

	/** 
	 * Transforms a point from the view's screen-space into world coordinates
	 * multiplies X, Y, Z by W before transforming. 
	 */
	FVector Deproject(const FPlane& ScreenPoint) const;

	/** transforms 2D screen coordinates into a 3D world-space origin and direction 
	 * @param ScreenPos - screen coordinates in pixels
	 * @param out_WorldOrigin (out) - world-space origin vector
	 * @param out_WorldDirection (out) - world-space direction vector
	 */
	void DeprojectFVector2D(const FVector2D& ScreenPos, FVector& out_WorldOrigin, FVector& out_WorldDirection);

	/** transforms 2D screen coordinates into a 3D world-space origin and direction 
	 * @param ScreenPos - screen coordinates in pixels
	 * @param ViewRect - view rectangle
	 * @param InvViewMatrix - inverse view matrix
	 * @param InvProjMatrix - inverse projection matrix
	 * @param out_WorldOrigin (out) - world-space origin vector
	 * @param out_WorldDirection (out) - world-space direction vector
	 */
	static void DeprojectScreenToWorld(const FVector2D& ScreenPos, const FIntRect& ViewRect, const FMatrix& InvViewMatrix, const FMatrix& InvProjMatrix, FVector& out_WorldOrigin, FVector& out_WorldDirection);

	inline FVector GetViewRight() const { return ViewMatrices.ViewMatrix.GetColumn(0); }
	inline FVector GetViewUp() const { return ViewMatrices.ViewMatrix.GetColumn(1); }
	inline FVector GetViewDirection() const { return ViewMatrices.ViewMatrix.GetColumn(2); }