中间的红色框包起来的是在light's post−perspective space中的视锥,红色框是构造出的trapezoidal,外围的是在trapezoidal space中的视锥.其中蓝色的表示视锥的Near Plane,绿色的表示Far Plane和边.
通过视锥计算梯形的代码:
HRESULT CTrapezoidalShadowMap::ComplteLightPostPerspectiveTrapezoidal(SFrustum& frustum,D3DXMATRIX& lightviewproj,D3DXVECTOR3& topl,D3DXVECTOR3& topr,D3DXVECTOR3& bottoml,D3DXVECTOR3& bottomr,D3DXVECTOR3& intersection)
{
D3DXVECTOR3 t_frustumvertex[9];
// 转换到Light's Post-Perspective Space
D3DXVec3TransformCoordArray( t_frustumvertex, sizeof(D3DXVECTOR3), frustum.m_Vertexs, sizeof(D3DXVECTOR3), &lightviewproj, sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3) );
for (int i=0;i<9;++i)
{
t_frustumvertex[i].z=0.0f;
}
// 求出中轴线
D3DXVECTOR3 t_topcenter =0.25*(t_frustumvertex[0]+t_frustumvertex[1]+t_frustumvertex[2]+t_frustumvertex[3]);
D3DXVECTOR3 t_bottomcenter =0.25*(t_frustumvertex[4]+t_frustumvertex[5]+t_frustumvertex[6]+t_frustumvertex[7]);
D3DXVECTOR3 t_centerline = t_topcenter - t_bottomcenter;
D3DXVec3Normalize(&t_centerline,&t_centerline);
// 平移和旋转使得中轴线的中点在Light's Post-Perspective Space中点,方向指向Light's Post-Perspective Space的Y轴
D3DXMATRIX t_trans;
D3DXMatrixTranslation(&t_trans,-0.5f*(t_topcenter.x+t_bottomcenter.x),-0.5f*(t_topcenter.y+t_bottomcenter.y),0);
D3DXMATRIX t_rotation;
float t_angle=acosf(D3DXVec3Dot(&t_centerline,&D3DXVECTOR3(0,1,0)));
if (t_centerline.x>0)
D3DXMatrixRotationZ(&t_rotation,-t_angle);
else
D3DXMatrixRotationZ(&t_rotation,t_angle);
t_trans*=t_rotation;
D3DXVec3TransformCoordArray( t_frustumvertex, sizeof(D3DXVECTOR3), t_frustumvertex, sizeof(D3DXVECTOR3), &t_trans, sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3) );
// 求出2D AABB
BoundingBox frustumAABB2D( t_frustumvertex, (sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3)-1) );
// 计算梯形的四个顶点
D3DXVECTOR3 t_topl,t_topr,t_bottoml,t_bottomr;
D3DXVECTOR3 t_side[4];
float t_value[4];
for (int i=0;i<4;++i)
{
t_side[i]=t_frustumvertex[i]-t_frustumvertex[i+4];
D3DXVec3Normalize(&t_side[i],&t_side[i]);
t_value[i]=D3DXVec3Dot(&t_side[i],&D3DXVECTOR3(0,1,0));
}
float t_min=1.0f;
int t_no;
for (int i=0;i<4;++i)
{
if (t_side[i].x>0)
continue;
if (t_value[i]<t_min)
{
t_min=t_value[i];
t_no=i;
}
}
t_topl.y=frustumAABB2D.maxPt.y;
t_topl.x=-(t_frustumvertex[8].y-frustumAABB2D.maxPt.y)*tanf(acosf(t_value[t_no]));
t_bottoml.y=frustumAABB2D.minPt.y;
t_bottoml.x=-(t_frustumvertex[8].y-frustumAABB2D.minPt.y)*tanf(acosf(t_value[t_no]));
t_min=1.0f;
for (int i=0;i<4;++i)
{
if (t_side[i].x<0)
continue;
if (t_value[i]<t_min)
{
t_min=t_value[i];
t_no=i;
}
}
t_topr.y=frustumAABB2D.maxPt.y;
t_topr.x=(t_frustumvertex[8].y-frustumAABB2D.maxPt.y)*tanf(acosf(t_value[t_no]));
t_bottomr.y=frustumAABB2D.minPt.y;
t_bottomr.x=(t_frustumvertex[8].y-frustumAABB2D.minPt.y)*tanf(acosf(t_value[t_no]));
// 将梯形四个顶点和两边的交点变换回Light's Post-Perspective Space
D3DXMATRIX t_invtrans;
D3DXMatrixInverse(&t_invtrans,NULL,&t_trans);
D3DXVec3TransformCoord(&topl,&t_topl,&t_trans);
D3DXVec3TransformCoord(&topr,&t_topr,&t_trans);
D3DXVec3TransformCoord(&bottoml,&t_bottoml,&t_trans);
D3DXVec3TransformCoord(&bottomr,&t_bottomr,&t_trans);
D3DXVec3TransformCoord(&intersection,&t_frustumvertex[8],&t_trans);
//
return S_OK;
};