> あと一つ、出来たら教え頂きたいことがありまして、そのレンダリングされないような処理を、
> フレーム単位で視野判定を行ってしているとおっしゃていますがどういったやり方というかアルゴリズムなのか少し教えていただけると助かります。
SetDrawArea や SetCameraNearFar が実行されたタイミングで事前に『任意の座標』が
視錐台の上下左右奥手前の6面のそれぞれ視錐台に対して内側にあるか外側にあるかを判定するために
必要な情報を計算しておきます
実際のソース( DxGraphics.cpp の Graphics_DrawSetting_RefreshBlend3DTransformMatrix 関数内 )は以下のようになっています
GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.top, 0.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.top, 0.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.bottom, 0.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.bottom, 0.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.top, 1.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.top, 1.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.bottom, 1.0 ) ) ;
GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.bottom, 1.0 ) ) ;
VECTOR_D Normal ;
// XZ平面
Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ) ) ;
CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 0 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ], &Normal ) ;
Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ] ) ) ;
CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 1 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ], &Normal ) ;
// YZ平面
Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ] ) ) ;
CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 2 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ], &Normal ) ;
Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ) ) ;
CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 3 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ], &Normal ) ;
// XY平面
Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ) ) ;
CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 4 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ], &Normal ) ;
Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ] ) ) ;
CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 5 ], &GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ], &Normal ) ;
フレームが視野に入っているかの判定では、フレームに含まれるメッシュの全頂点座標から
最小のX,Y,Z座標・最大のX,Y,Z座標で形成されるキューブの8頂点と、事前に計算しておいた視錐台判定用の情報を使って
キューブが視錐台の中に入っているかどうかを調べます
実際のソースは以下のようになっています
DxModel.cpp の MV1DrawModelBase 関数内
// 可視チェック用頂点座標を算出する
Tmp = Frame->BaseData->MaxPosition ; VectorTransform4X4CT( &CheckPos[ 0 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.x = Frame->BaseData->MinPosition.x ; VectorTransform4X4CT( &CheckPos[ 1 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.y = Frame->BaseData->MinPosition.y ; VectorTransform4X4CT( &CheckPos[ 2 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.x = Frame->BaseData->MaxPosition.x ; VectorTransform4X4CT( &CheckPos[ 3 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.z = Frame->BaseData->MinPosition.z ; VectorTransform4X4CT( &CheckPos[ 4 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.y = Frame->BaseData->MaxPosition.y ; VectorTransform4X4CT( &CheckPos[ 5 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.x = Frame->BaseData->MinPosition.x ; VectorTransform4X4CT( &CheckPos[ 6 ], &Tmp, &Frame->LocalWorldMatrix ) ;
Tmp.y = Frame->BaseData->MinPosition.y ; VectorTransform4X4CT( &CheckPos[ 7 ], &Tmp, &Frame->LocalWorldMatrix ) ;
// 可視チェック
if( Graphics_Camera_CheckCameraViewClip_Box_PosDim( CheckPos ) == TRUE )
continue ;
DxGraphics.cpp の Graphics_Camera_CheckCameraViewClip_Box_PosDim 関数
// 8座標で形作るボックスがカメラの視界に入っているかどうかを判定する( 戻り値 TRUE:視界に入っていない FALSE:視界に入っている )( CheckPosは VECTOR 8個分の配列の先頭アドレス、配列の各要素番号の内容 0:+x +y +z 1:-x +y +z 2:-x -y +z 3:+x -y +z 4:+x -y -z 5:+x +y -z 6:-x +y -z 7:-x -y -z )
extern int Graphics_Camera_CheckCameraViewClip_Box_PosDim( VECTOR *CheckBoxPos )
{
BYTE clip[ 8 ] ;
VECTOR *pos ;
int i ;
// 各頂点が可視領域に入っているかどうかを調べる
pos = CheckBoxPos ;
for( i = 0 ; i < 8 ; i ++, pos ++ )
{
clip[ i ] = 0 ;
if( GSYS.DrawSetting.ClippingPlane[ 0 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 0 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 0 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 0 ].w < 0.0f ) clip[ i ] |= CLIP_XM ;
if( GSYS.DrawSetting.ClippingPlane[ 1 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 1 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 1 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 1 ].w < 0.0f ) clip[ i ] |= CLIP_XP ;
if( GSYS.DrawSetting.ClippingPlane[ 2 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 2 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 2 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 2 ].w < 0.0f ) clip[ i ] |= CLIP_YM ;
if( GSYS.DrawSetting.ClippingPlane[ 3 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 3 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 3 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 3 ].w < 0.0f ) clip[ i ] |= CLIP_YP ;
if( GSYS.DrawSetting.ClippingPlane[ 4 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 4 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 4 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 4 ].w < 0.0f ) clip[ i ] |= CLIP_ZM ;
if( GSYS.DrawSetting.ClippingPlane[ 5 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 5 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 5 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 5 ].w < 0.0f ) clip[ i ] |= CLIP_ZP ;
if( clip[ i ] == 0 ) return FALSE ;
}
// どれかの側に全ての頂点が寄っている場合は100%可視領域に入っていない
if( ( ( clip[0] & CLIP_XP ) && ( clip[1] & CLIP_XP ) &&
( clip[2] & CLIP_XP ) && ( clip[3] & CLIP_XP ) &&
( clip[4] & CLIP_XP ) && ( clip[5] & CLIP_XP ) &&
( clip[6] & CLIP_XP ) && ( clip[7] & CLIP_XP ) ) ||
( ( clip[0] & CLIP_XM ) && ( clip[1] & CLIP_XM ) &&
( clip[2] & CLIP_XM ) && ( clip[3] & CLIP_XM ) &&
( clip[4] & CLIP_XM ) && ( clip[5] & CLIP_XM ) &&
( clip[6] & CLIP_XM ) && ( clip[7] & CLIP_XM ) ) ||
( ( clip[0] & CLIP_YP ) && ( clip[1] & CLIP_YP ) &&
( clip[2] & CLIP_YP ) && ( clip[3] & CLIP_YP ) &&
( clip[4] & CLIP_YP ) && ( clip[5] & CLIP_YP ) &&
( clip[6] & CLIP_YP ) && ( clip[7] & CLIP_YP ) ) ||
( ( clip[0] & CLIP_YM ) && ( clip[1] & CLIP_YM ) &&
( clip[2] & CLIP_YM ) && ( clip[3] & CLIP_YM ) &&
( clip[4] & CLIP_YM ) && ( clip[5] & CLIP_YM ) &&
( clip[6] & CLIP_YM ) && ( clip[7] & CLIP_YM ) ) ||
( ( clip[0] & CLIP_ZP ) && ( clip[1] & CLIP_ZP ) &&
( clip[2] & CLIP_ZP ) && ( clip[3] & CLIP_ZP ) &&
( clip[4] & CLIP_ZP ) && ( clip[5] & CLIP_ZP ) &&
( clip[6] & CLIP_ZP ) && ( clip[7] & CLIP_ZP ) ) ||
( ( clip[0] & CLIP_ZM ) && ( clip[1] & CLIP_ZM ) &&
( clip[2] & CLIP_ZM ) && ( clip[3] & CLIP_ZM ) &&
( clip[4] & CLIP_ZM ) && ( clip[5] & CLIP_ZM ) &&
( clip[6] & CLIP_ZM ) && ( clip[7] & CLIP_ZM ) ) )
return TRUE ;
// ここにきたら見えているということ
return FALSE ;
}
DXライブラリのソースはダウンロードページからダウンロードすることができますので、
よろしければ直にご覧になってみてください