欢迎阅读指正和转载,但请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
 
深度探索DxFramework
 
第10章 进入三维的世界 6
 
10.6.4.坐标变换
 
//把某顶点从它的局部坐标变换到屏幕坐标
void C_Viewport::LocalToScreen(D3DXVECTOR3* p_ScreenOut, D3DXVECTOR3* p_LocalIn,D3DXMATRIX* p_WorldMatrix)
{
       D3DXVec3Project(p_ScreenOut, p_LocalIn, &d3dViewport,&projection, &view, p_WorldMatrix);
}

//把某顶点从它的局部坐标变换到世界坐标
void C_Viewport::LocalToWorld(D3DXVECTOR3* p_WorldOut, D3DXVECTOR3* p_LocalIn, D3DXMATRIX* p_WorldMatrix)
{
    D3DXVec3TransformCoord(p_WorldOut, p_LocalIn,p_WorldMatrix);
}

//把某顶点从它的局部坐标变换到观察坐标
void C_Viewport::LocalToView(D3DXVECTOR3* p_ViewOut,D3DXVECTOR3* p_LocalIn,D3DXMATRIX* p_WorldMatrix)
{
    D3DXVECTOR3 worldTemp;
    D3DXVec3TransformCoord(&worldTemp, p_LocalIn, p_WorldMatrix);
    D3DXVec3TransformCoord(p_ViewOut, &worldTemp, &view);
}

//把某顶点从世界坐标变换到屏幕坐标
void C_Viewport::WorldToScreen(D3DXVECTOR3* p_ScreenOut,D3DXVECTOR3* p_WorldIn) 
{
     D3DXVec3Project(p_ScreenOut, p_WorldIn, &d3dViewport,&projection, &view, &matIdentity);
}
 
10.6.5.视截体相交判断
 
//判断某包围盒和视截体的相交情况
IN_VIEWPORT_TYPE C_Viewport::InViewport(C_BoundingBox* p_BoundingBox) 
{
    INTERSECTION_TYPE tempIntersect = p_FrustumVolume->IsIntersecting(p_BoundingBox);
    if (tempIntersect == NOT_INTERSECTING) 
        return NOT_IN_VIEWPORT;
    if (tempIntersect == COMPLETELY_COVER) 
        return COMPLETELY_IN_VIEWPORT;
    return PARTIALLY_IN_VIEWPORT;
}

//判断某3D game object与视截体的相交情况
IN_VIEWPORT_TYPE C_Viewport::InViewport(C_GameObject3D*  p_GameObject3D)
{
    C_BoundingBox* p_BoundingBox = p_GameObject3D->GetTransformedBoundingBox();
    
    if (p_BoundingBox == NULL)
    {
        return COMPLETELY_IN_VIEWPORT;
    }
    INTERSECTION_TYPE tempIntersect = p_FrustumVolume->
                            IsIntersecting(p_BoundingBox);
    if (tempIntersect == NOT_INTERSECTING) 
        return NOT_IN_VIEWPORT;
    if (tempIntersect == COMPLETELY_COVER) 
        return COMPLETELY_IN_VIEWPORT;
    
    return PARTIALLY_IN_VIEWPORT;
}

IN_VIEWPORT_TYPE C_Viewport::LazyInViewport(C_BoundingBox*  p_BoundingBox) 
{
    INTERSECTION_TYPE tempIntersect = p_FrustumVolume->LazyIsIntersecting(p_BoundingBox);
    if (tempIntersect == NOT_INTERSECTING) 
        return NOT_IN_VIEWPORT;
    if (tempIntersect == COMPLETELY_COVER) 
        return COMPLETELY_IN_VIEWPORT;
    return PARTIALLY_IN_VIEWPORT;
}

IN_VIEWPORT_TYPE C_Viewport::LazyInViewport(C_GameObject3D* p_GameObject3D)
{
    C_BoundingBox* p_BoundingBox = p_GameObject3D->GetTransformedBoundingBox();
    if(p_BoundingBox == NULL) 
    {
        return COMPLETELY_IN_VIEWPORT;
     }
    INTERSECTION_TYPE tempIntersect  = p_FrustumVolume->LazyIsIntersecting(p_BoundingBox);
    
    if (tempIntersect == NOT_INTERSECTING)
       return NOT_IN_VIEWPORT;
     
    if (tempIntersect == COMPLETELY_COVER)
       return COMPLETELY_IN_VIEWPORT;
    
   return PARTIALLY_IN_VIEWPORT;
}

 
10.6.6.相机状态更新
 
void C_Viewport::Update() 
{
    C_View::p_D3DDevice->SetTransform(D3DTS_VIEW, &view);
    C_View::p_D3DDevice->SetTransform(D3DTS_PROJECTION, &projection);

    if (!fogEnable) 
    {
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGENABLE,    FALSE);
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGCOLOR,D3DCOLOR_ARGB(0,0,0,0) );
    } 
    else
    {
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGENABLE,TRUE);
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGCOLOR, fogColor );
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGTABLEMODE, fogMode );
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*) (&fogStartZ)) );
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGEND,*((DWORD*) (&fogEndZ)) );
        C_View::p_D3DDevice->SetRenderState(D3DRS_FOGDENSITY, *((DWORD*) (&fogDensity)) );
    }
}

void C_Viewport::UpdateFrustum()
{
    // Quaternions that are used to rotate around Y 
    // axis and X axis(= Cross(lookatnormal, yNormal) )
    D3DXQUATERNION rotateYQPlus, rotateXQPlus;
    D3DXQUATERNION rotateYQMinus, rotateXQMinus;      

    // Matrices that are used to rotate the 
    // corner points of Frustum volume
    D3DXMATRIX    rotateYMatPlus, rotateXMatPlus;
    D3DXMATRIX  rotateYMatMinus, rotateXMatMinus; 

    // Build the quaternions
    D3DXQuaternionRotationAxis(&rotateYQPlus, &yNormal, fovX / 2);
    D3DXQuaternionRotationAxis(&rotateXQPlus, &xNormal, fovY / 2);
    D3DXQuaternionRotationAxis(&rotateYQMinus, &yNormal, -fovX / 2);
    D3DXQuaternionRotationAxis(&rotateXQMinus, &xNormal, -fovY / 2);

    // Obtain rotation matrices around  Y and X axis from quaternions
    D3DXMatrixRotationQuaternion(&rotateYMatPlus, &rotateYQPlus);
    D3DXMatrixRotationQuaternion(&rotateXMatPlus, &rotateXQPlus);
    D3DXMatrixRotationQuaternion(&rotateYMatMinus, &rotateYQMinus);
    D3DXMatrixRotationQuaternion(&rotateXMatMinus, &rotateXQMinus);

    // Find distance from the camera to the 4 
    // corners at z = zNear of the viewing volume 
    float distanceToNearPlane = (float)(zNear / (cos(fovX / 2) * cos(fovY / 2)));

    // Find distance from the camera to the 4 
    // corners at z = zfat of the viewing volume 
    float distanceToFarPlane = (float)(zFar / (cos(fovX / 2) * cos(fovY / 2)));
    // Right Bottom Near
    D3DXVec3TransformCoord(&point[0], &zNormal,&rotateYMatPlus);
    D3DXVec3TransformCoord(&point[0], &point[0], &rotateXMatMinus);
    point[0] *= distanceToNearPlane;

    // Right Top Near
    D3DXVec3TransformCoord(&point[1], &zNormal, &rotateYMatPlus);
    D3DXVec3TransformCoord(&point[1], &point[1], &rotateXMatPlus);
    point[1] *= distanceToNearPlane;

    // Left Top Near    
    D3DXVec3TransformCoord(&point[2], &zNormal, &rotateYMatMinus);
    D3DXVec3TransformCoord(&point[2], &point[2], &rotateXMatPlus);
    point[2] *= distanceToNearPlane;

    // Left Bottom Near
    D3DXVec3TransformCoord(&point[3],&zNormal, &rotateYMatMinus);
    D3DXVec3TransformCoord(&point[3], &point[3], &rotateXMatMinus);
    point[3] *= distanceToNearPlane;

    // Right Bottom Far
    D3DXVec3TransformCoord(&point[4],&zNormal, &rotateYMatPlus);
    D3DXVec3TransformCoord(&point[4],
    &point[4], &rotateXMatMinus);
    point[4] *= distanceToFarPlane;

    // Right Top Far
    D3DXVec3TransformCoord(&point[5], &zNormal, &rotateYMatPlus);
    D3DXVec3TransformCoord(&point[5], &point[5], &rotateXMatPlus);
    point[5] *= distanceToFarPlane;

    // Left Top Far
    D3DXVec3TransformCoord(&point[6], &zNormal, &rotateYMatMinus);
    D3DXVec3TransformCoord(&point[6],&point[6], &rotateXMatPlus);
    point[6] *= distanceToFarPlane;

    // Left Bottom Far
    D3DXVec3TransformCoord(&point[7], &zNormal, &rotateYMatMinus);
    D3DXVec3TransformCoord(&point[7], &point[7], &rotateXMatMinus);
    point[7] *= distanceToFarPlane;

    int i;
    // Translate the points to the origin, camera position
    for (i = 0; i < 8; i++)
       point[i] += position;

    // Obtain the 6 planes for the Frustum Volume
    D3DXPlaneFromPoints(&plane[0], &point[2],&point[1], &point[0]); //Near
    D3DXPlaneFromPoints(&plane[1], &point[5], &point[6], &point[4]); //Far
    D3DXPlaneFromPoints(&plane[2], &point[7],&point[6], &point[2]); //Left
    D3DXPlaneFromPoints(&plane[3], &point[1], &point[5], &point[0]); //Right
    D3DXPlaneFromPoints(&plane[4], &point[4], &point[3], &point[0]); //Bottom
    D3DXPlaneFromPoints(&plane[5], &point[2], &point[5], &point[1]); //Top

    // Set the bounding box of Frustum Volume
    // to use these points and plane data
    p_FrustumVolume->SetBoundingBox(point, plane);    
}