irrlicht/source/Irrlicht.NET/Plane3D.h

211 lines
6.3 KiB
C++

// Copyright (C) 2002-2006 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#pragma once
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Irrlicht
{
namespace Core
{
/// <summary>
/// Enumeration for intersection relations of 3d objects
/// </summary>
public __value enum IntersectionRelation3D
{
ISREL3D_FRONT = 0,
ISREL3D_BACK,
ISREL3D_PLANAR,
ISREL3D_SPANNING,
ISREL3D_CLIPPED
};
/// <summary>
/// Specifies a two dimensional size.
/// </summary>
public __value class Plane3D
{
public:
// Constructors
Plane3D(): Normal(0,1,0) { RecalculateD(Vector3D(0,0,0)); };
Plane3D(Vector3D MPoint, Vector3D Normal) : Normal(Normal) { RecalculateD(MPoint); };
Plane3D(float px, float py, float pz, float nx, float ny, float nz) : Normal(nx, ny, nz) { RecalculateD(Vector3D(px, py, pz)); };
Plane3D(Vector3D point1, Vector3D point2, Vector3D point3) { SetPlane(point1, point2, point3); };
void SetPlane(Vector3D point, Vector3D nvector)
{
Normal = nvector;
Normal.Normalize();
RecalculateD(point);
}
void SetPlane(Vector3D nvect, float d)
{
Normal = nvect;
D = d;
}
void SetPlane(Vector3D point1, Vector3D point2, Vector3D point3)
{
// creates the plane from 3 memberpoints
Normal = (point2 - point1).CrossProduct(point3 - point1);
Normal.Normalize();
RecalculateD(point1);
}
/// <summary>
/// Returns an intersection with a 3d line.
/// </summary>
/// <param name="lineVect"> Vector of the line to intersect with.</param>
/// <param name="linePoint"> Point of the line to intersect with.</param>
/// <param name="outIntersection"> Place to store the intersection point, if there is one.</param>
/// <returns> Returns true if there was an intersection, false if there was not.
bool GetIntersectionWithLine(Vector3D linePoint, Vector3D lineVect,
[PARAMFLAG::Out] Vector3D& outIntersection)
{
float t2 = Normal.DotProduct(lineVect);
if (t2 == 0)
return false;
float t =- (Normal.DotProduct(linePoint) + D) / t2;
outIntersection = linePoint + (lineVect * t);
return true;
}
/// <summary>
/// Returns an intersection with a 3d line, limited between two 3d points.
/// </summary>
/// <param name="linePoint1"> Point 1 of the line.</param>
/// <param name="linePoint2"> Point 2 of the line.</param>
/// <param name="outIntersection"> Place to store the intersection point, if there is one.</param>
/// <returns> Returns true if there was an intersection, false if there was not.</returns>
bool GetIntersectionWithLimitedLine(Vector3D linePoint1,
Vector3D linePoint2, [PARAMFLAG::Out] Vector3D& outIntersection)
{
return ( GetIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) &&
outIntersection.IsBetweenPoints(linePoint1, linePoint2));
}
/// <summary>
/// Classifies the relation of a point to this plane.
/// </summary>
/// <param name="point"> Point to classify its relation.</param>
/// <returns> Returns ISREL3D_FRONT if the point is in front of the plane,
/// ISREL3D_BACK if the point is behind of the plane, and
/// ISREL3D_PLANAR if the point is within the plane.</returns>
IntersectionRelation3D ClassifyPointRelation(Vector3D point)
{
float d = Normal.DotProduct(point) + D;
if (d < -ROUNDING_ERROR)
return ISREL3D_FRONT;
if (d > ROUNDING_ERROR)
return ISREL3D_BACK;
return ISREL3D_PLANAR;
}
/// <summary>
/// Recalculates the distance from origin by applying
/// a new member point to the plane.
/// </summary>
void RecalculateD(Vector3D MPoint)
{
D = - MPoint.DotProduct(Normal);
}
/// <summary>
/// Returns a member point of the plane.
/// </summary>
Vector3D GetMemberPoint()
{
return Normal * -D;
}
/// <summary>
/// Tests if there is a intersection between this plane and another
/// </summary>
/// <returns> Returns true if there is a intersection.</returns>
bool ExistsInterSection(Plane3D other)
{
Vector3D cross = other.Normal.CrossProduct(Normal);
return cross.GetLength() > 1e-08f;
}
/// <summary>
/// Intersects this plane with another.
/// </summary>
/// <returns> Returns true if there is a intersection, false if not.</returns>
bool GetIntersectionWithPlane(Plane3D other, [PARAMFLAG::Out] Vector3D& outLinePoint,
[PARAMFLAG::Out] Vector3D& outLineVect)
{
double fn00 = Normal.GetLength();
double fn01 = Normal.DotProduct(other.Normal);
double fn11 = other.Normal.GetLength();
double det = fn00*fn11 - fn01*fn01;
if (mfabs((float)det) < 1e-08f)
return false;
det = 1.0 / det;
double fc0 = (fn11*-D + fn01*other.D) * det;
double fc1 = (fn00*-other.D + fn01*D) * det;
outLineVect = Normal.CrossProduct(other.Normal);
outLinePoint = Normal*(float)fc0 + other.Normal*(float)fc1;
return true;
}
/// <summary>
/// Returns the intersection point with two other planes if there is one.
/// </summary>
bool GetIntersectionWithPlanes(Plane3D o1,
Plane3D o2, [PARAMFLAG::Out] Vector3D& outPoint)
{
Vector3D linePoint, lineVect;
if (GetIntersectionWithPlane(o1, linePoint, lineVect))
return o2.GetIntersectionWithLine(linePoint, lineVect, outPoint);
return false;
}
/// <summary>
/// Returns if the plane is front of backfacing. Note that this only
/// works if the normal is Normalized.
/// </summary>
/// <param name="lookDirection"> Look direction.</param>
/// <returns> Returns true if the plane is front facing, which mean it would
/// be visible, and false if it is backfacing.</returns>
bool IsFrontFacting(Vector3D lookDirection)
{
return Normal.DotProduct(lookDirection) <= 0.0f;
}
/// <summary>
/// Returns the distance to a point. Note that this only
/// works if the normal is Normalized.
/// </summary>
float GetDistanceTo(Vector3D point)
{
return point.DotProduct(Normal) + D;
}
// member variables
float D; // distance from origin
Vector3D Normal; // normal vector
};
}
}