平面
将三维物体表面剖分为一系列的三角形面,物体的光照亮度处理就转化为对这些平面三角形的照明处理,从而可简单地通过平面三角形的法向量与光的入射方向的夹角,来确定各种入射光对平面上每一点所贡献的亮度值。
对于三角形3个顶点p0,p1,p2构成的平面,选取一个垂直于该平面的法向量n。假设点p为平面上的任意一点,由于n . (p - p0) = 0,从而n . p
- n . p0 = 0,由此展开向量的点积运算可知,平面方程具有如下的一般形式:ax+by+cz+d=0。如果要具体求出平面的方程,可取n=(p1-p0) x
(p2 - p0)计算出来。
因为平面的方程式由4个系数a, b, c,
d就可确定,因此,DirectX提供了如下的D3DXPLANE结构体保存方程式的4个系数,当然结构体还提供了基于方程式系数的加减乘除等运算。
typedef struct D3DXPLANE
{
#ifdef __cplusplus
public:
D3DXPLANE() {}
D3DXPLANE( CONST FLOAT* );
D3DXPLANE( CONST D3DXFLOAT16* );
D3DXPLANE( FLOAT a, FLOAT b, FLOAT c, FLOAT d );
// casting
operator FLOAT* ();
operator CONST FLOAT* () const;
// assignment operators
D3DXPLANE& operator *= ( FLOAT );
D3DXPLANE& operator /= ( FLOAT );
// unary operators
D3DXPLANE operator + () const;
D3DXPLANE operator - () const;
// binary operators
D3DXPLANE operator * ( FLOAT ) const;
D3DXPLANE operator / ( FLOAT ) const;
friend D3DXPLANE operator * ( FLOAT, CONST D3DXPLANE& );
BOOL operator == ( CONST D3DXPLANE& ) const;
BOOL operator != ( CONST D3DXPLANE& ) const;
#endif //__cplusplus
FLOAT a, b, c, d;
} D3DXPLANE, *LPD3DXPLANE;
DirectX还提供了基于三点的向量求平面的
D3DXPlaneFromPoints函数以及基于一点和一个法向量求平面的D3DXPlaneFromPointNormal函数。
Constructs a
plane from three points.
D3DXPLANE * D3DXPlaneFromPoints(
D3DXPLANE * pOut,
CONST D3DXVECTOR3 * pV1,
CONST D3DXVECTOR3 * pV2,
CONST D3DXVECTOR3 * pV3
);
Parameters
- pOut
- [in, out] Pointer to the D3DXPLANE structure that is the result of the
operation.
- pV1
- [in] Pointer to a D3DXVECTOR3 structure, defining one of the points used
to construct the plane.
- pV2
- [in] Pointer to a D3DXVECTOR3 structure, defining one of the
points used to construct the plane.
- pV3
- [in] Pointer to a D3DXVECTOR3 structure, defining one of the
points used to construct the plane.
Return Values
Pointer to the D3DXPLANE structure constructed from the given points.
Remarks
The return value for this function is the same value returned in the pOut
parameter. In this way, the D3DXPlaneFromPoints function can be used as a
parameter for another function.
Constructs a plane from a point and a normal.
D3DXPLANE * D3DXPlaneFromPointNormal(
D3DXPLANE * pOut,
CONST D3DXVECTOR3 * pPoint,
CONST D3DXVECTOR3 * pNormal
);
Parameters
- pOut
- [in, out] Pointer to the D3DXPLANE structure that is the result of the
operation.
- pPoint
- [in] Pointer to a D3DXVECTOR3 structure, defining the point used to
construct the plane.
- pNormal
- [in] Pointer to a D3DXVECTOR3 structure, defining the normal used
to construct the plane.
Return Values
Pointer to the D3DXPLANE structure constructed from the point and the
normal.
Remarks
The return value for this function is the same value returned in the pOut
parameter. In this way, the D3DXPlaneFromPointNormal function can be used
as a parameter for another function.
要正确运行以下的示例程序,需要在工程中包含d3dx9.lib,或者在main函数前加入
#pragma comment(lib, "d3dx9.lib")
以指示编译器链接d3dx9.lib。
代码示例:
#include <stdio.h>
#include <D3DX9Math.h>
#pragma warning(disable : 4305)
int main()
{
D3DXVECTOR3 P0(8.0, -3.0, 6.0);
D3DXVECTOR3 P1(2.0, -3.0, -5.0);
D3DXVECTOR3 P2(-1.0, -3.0, 10.0);
D3DXPLANE plane;
D3DXPlaneFromPoints(&plane, &P0, &P1, &P2);
printf("Plane equation: %fx + %fy + %fz + %f = 0", plane.a, plane.b, plane.c, plane.d);
printf("\n\n\n");
return 0;
}
结果输出:
Plane equation: 0.000000x + 1.000000y + 0.000000z + 3.000000 = 0
直线与平面的交点
Finds the intersection between a plane and a line.
D3DXVECTOR3 * D3DXPlaneIntersectLine(
D3DXVECTOR3 * pOut,
CONST D3DXPLANE * pP,
CONST D3DXVECTOR3 * pV1,
CONST D3DXVECTOR3 * pV2
);
Parameters
- pOut
- [in, out] Pointer to a D3DXVECTOR3 structure, identifying the
intersection between the specified plane and line.
- pP
- [in] Pointer to the source D3DXPLANE structure.
- pV1
- [in] Pointer to a source D3DXVECTOR3 structure, defining a line
starting point.
- pV2
- [in] Pointer to a source D3DXVECTOR3 structure, defining a line
ending point.
Return Values
Pointer to a D3DXVECTOR3 structure that is the intersection between
the specified plane and line.
Remarks
If the line is parallel to the plane, NULL is returned.
The return value for this function is the same value returned in the pOut
parameter. In this way, the D3DXPlaneIntersectLine function can be used
as a parameter for another function.
代码示例
#include <stdio.h>
#include <D3DX9Math.h>
#pragma comment(lib, "d3dx9.lib")
#pragma warning(disable : 4305)
int main()
{
D3DXVECTOR3 A(0, 0, 0);
D3DXVECTOR3 B(5, 5, 5);
D3DXPLANE plane(0, 1, 0, -1); // equation: x = 1
D3DXVECTOR3 intersect_point;
D3DXPlaneIntersectLine(&intersect_point, &plane, &A, &B);
// intersect point must be: (1, 1, 1)
printf("Intersect point: (%f, %f, %f)\n\n", intersect_point.x, intersect_point.y, intersect_point.z);
return 0;
}
输出:
Intersect point: (1.000000, 1.000000, 1.000000)
点和平面的位置关系
对于1个给定了法向量n和内部一点p0的平面,任意1点p与该平面的位置关系可用两向量的点积n . (p - p0) 进行判断,分为如下的3种情形:
(1) 点p在法向量n的同一侧,即n . (p - p0) > 0
(2) 点p在平面上,即n . (p - p0) = 0
(3) 点p在法向量n的反侧,即n . (p - p0) < 0
对于以方程式ax+by+cz+d=0给出的平面,由系数a, b和c构成的向量(a, b, c)必然是1个垂直于该平面的向量法向量。
(证明如下:设平面上任意两个点(x1,y1,z1), (x2,y2,z2),代入方程:
ax1+by1+cz1+d=0; ax2+by2+cz2+d=0 ;
====>
a(x1-x2)+b(y1-y2)+c(z1-z2)=0
====>
(a,b,c)(x1-x2, y1-y2, z1-z2)=0
即点积为0,因为两点是任意的,所以具有一般性,即向量垂直与平面内任意一条直线。)
称向量(a, b, c)为平面ax + by + cz +d = 0的默认法向量。
判断一点p(x0, y0, z0)与ax+by+z+d=0平面的位置关系,可以直接利用ax0+by0+cz0+d的符号来决定。
ax0 +by0+cz0+d > 0表示点p在默认法向量的一侧,也可以说是位于平面的前方。
ax0+by0+cz0+d = 0表示点p在平面上。
ax0+by0+cz0+d < 0表示点p在默认法向量的另一侧,也可以说是位于平面的后方。
平面(a, b, c, d)与任意点(x0, y0, z0)的ax0 + by0 +
cz0值,可用DirectX提供的D3DXPlaneDotCoord函数计算出来,利用该函数返回值的符号可决定点在平面的那一侧。
Computes the dot product of a plane and a 3D vector. The w parameter of the
vector is assumed to be 1.
FLOAT D3DXPlaneDotCoord(
CONST D3DXPLANE * pP,
CONST D3DXVECTOR3 * pV
);
Parameters
- pP
- [in] Pointer to a source D3DXPLANE structure.
- pV
- [in] Pointer to a source D3DXVECTOR3 structure.
Return Values
The dot product of the plane and 3D vector.
Remarks
Given a plane (a, b, c, d) and a 3D vector (x, y, z) the return value of this
function is a*x + b*y + c*z + d*1. The D3DXPlaneDotCoord function is
useful for determining the plane's relationship with a coordinate in 3D space.
如果要计算平面法线和另一法线的夹角,可使用D3DXPlaneDotNormal。
Computes the dot product of a plane and a 3D vector. The w parameter of the
vector is assumed to be 0.
FLOAT D3DXPlaneDotNormal(
CONST D3DXPLANE * pP,
CONST D3DXVECTOR3 * pV
);
Parameters
- pP
- [in] Pointer to a source D3DXPLANE structure.
- pV
- [in] Pointer to a source D3DXVECTOR3 structure.
Return Values
The dot product of the plane and 3D vector.
Remarks
Given a plane (a, b, c, d) and a 3D vector (x, y, z) the return value of this
function is a*x + b*y + c*z + d*0. The D3DXPlaneDotNormal function is
useful for calculating the angle between the normal of the plane, and another
normal.
平面单位化:
如果平面ax+by+cz+d=0的默认法向量n =(a,b,c)为单位向量,那么该平面称为单位化平面。
Normalizes the
plane coefficients so that the plane normal has unit length.
D3DXPLANE * D3DXPlaneNormalize(
D3DXPLANE * pOut,
CONST D3DXPLANE * pP
);
Parameters
- pOut
- [in, out] Pointer to the D3DXPLANE structure that is the result of the
operation.
- pP
- [in] Pointer to the source D3DXPLANE structure.
Return Values
Pointer to a D3DXPLANE structure that represents the normal of the
plane.
Remarks
This function normalizes a plane so that |a,b,c| == 1.
The return value for this function is the same value returned in the pOut
parameter. In this way, this function can be used as a parameter for another
function.
代码示例:
#include <stdio.h>
#include <D3DX9Math.h>
#pragma warning(disable : 4305)
int main()
{
D3DXPLANE plane(1, 0, 0, -1);
D3DXVECTOR3 p(5, 0, 0);
float dot = D3DXPlaneDotCoord(&plane, &p);
printf("dot = %f\n\n", dot);
dot = D3DXPlaneDotNormal(&plane, &p);
printf("dot = %f\n\n", dot);
D3DXPLANE plane2(3, 4, 0, 0);
D3DXPlaneNormalize(&plane2, &plane2);
printf("After normalize: (%f, %f, %f, %f)\n\n", plane2.a, plane2.b, plane2.c, plane2.d);
return 0;
}
输出:
dot = 4.000000
dot = 5.000000
After normalize: (0.600000, 0.800000, 0.000000, 0.000000)