しかしこの方のプログラムのSetGroundPolygon関数のアルゴリズムが上手く理解できません。
ポリゴン内部に次フレームでの移動点が存在するかどうかを判定していること、何やら外積を使っていそうなことぐらいは理解できるのですが、atan2をどう用いているのか、回転角の総和と6.2fを比べる行為に何の意味があるのかわかりません。
お手数ですが是非ご回答下さい。
あわせて、3Dプログラミングにアルゴリズム等を紹介してくれる良いサイトなど御座いましたら是非教えて下さい。
// 接地ポリゴン情報をセット
int SetGroundPolygon( void )
{
int i,ResultFlag;
float TotalRad, ResultY;
VECTOR Position[3];
HITRESULT_LINE HitResult;
ResultY = Pc.NextPosition.y - PC_MAX_VERTICAL;
ResultFlag = 0;
for( i = 0 ; i < MapPoly.PolygonNum ; i++ ){
if( MapPoly.Polygons[ i ].MinPosition.x <= Pc.NextPosition.x && MapPoly.Polygons[ i ].MinPosition.z <= Pc.NextPosition.z &&
MapPoly.Polygons[ i ].MaxPosition.x >= Pc.NextPosition.x && MapPoly.Polygons[ i ].MaxPosition.z >= Pc.NextPosition.z){
Position[0] = MapPoly.Vertexs[ MapPoly.Polygons[ i ].VIndex[ 0 ] ].Position ;
Position[1] = MapPoly.Vertexs[ MapPoly.Polygons[ i ].VIndex[ 1 ] ].Position ;
Position[2] = MapPoly.Vertexs[ MapPoly.Polygons[ i ].VIndex[ 2 ] ].Position ;
// ポリゴンに座標が含まれているか
TotalRad = atan2(
(Position[0].x - Pc.NextPosition.x) * (Position[1].z - Pc.NextPosition.z) - (Position[0].z - Pc.NextPosition.z) * (Position[1].x - Pc.NextPosition.x),
(Position[0].x - Pc.NextPosition.x) * (Position[1].x - Pc.NextPosition.x) + (Position[0].z - Pc.NextPosition.z) * (Position[1].z - Pc.NextPosition.z)
) ;
TotalRad += atan2(
(Position[1].x - Pc.NextPosition.x) * (Position[2].z - Pc.NextPosition.z) - (Position[1].z - Pc.NextPosition.z) * (Position[2].x - Pc.NextPosition.x),
(Position[1].x - Pc.NextPosition.x) * (Position[2].x - Pc.NextPosition.x) + (Position[1].z - Pc.NextPosition.z) * (Position[2].z - Pc.NextPosition.z)
) ;
TotalRad += atan2(
(Position[2].x - Pc.NextPosition.x) * (Position[0].z - Pc.NextPosition.z) - (Position[2].z - Pc.NextPosition.z) * (Position[0].x - Pc.NextPosition.x),
(Position[2].x - Pc.NextPosition.x) * (Position[0].x - Pc.NextPosition.x) + (Position[2].z - Pc.NextPosition.z) * (Position[0].z - Pc.NextPosition.z)
) ;
if( abs(TotalRad) >= 6.2f ){
HitResult = HitCheck_Line_Triangle(
VGet( Pc.NextPosition.x, (Pc.NextPosition.y + PC_PASSAGE_BUMP), Pc.NextPosition.z ),
VGet( Pc.NextPosition.x, (Pc.NextPosition.y - PC_MAX_VERTICAL), Pc.NextPosition.z ),
Position[0], Position[1], Position[2]
) ;
if( (HitResult.Position.y <= Pc.Position.y + PC_PASSAGE_BUMP) && (HitResult.Position.y > ResultY) )
{
memcpy(Pc.GroundPolygon, Position, sizeof(Pc.GroundPolygon));
memcpy(Pc.GroundIndex , MapPoly.Polygons[ i ].VIndex, sizeof(Pc.GroundIndex));
Pc.GroundPoint = HitResult;
ResultY = HitResult.Position.y;
ResultFlag = 1;
}
}
}
}
return ResultFlag;
}