行列は使わずにというご要望にはお答えできませんが、おそらく埴輪さんが仰る動作をすると思います。
以前テストで作ったものなのでおかしな部分があるかもしれません(見直ししていません)。
カメラがY軸(付近)を通過したときに天地が逆転したように見えてしまうのはカメラの上方向をY軸に固定しているためです。
ですので、カメラの動きに合わせて適切な上方向を設定すると逆転現象がなくなります。
//- 以下、テストソース (SimpleModel.mqo を使用) -//
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int ModelHandle;
VECTOR CameraPos, FocusPos, HeadDir;
MATRIX RotUp, RotDown, RotRight, RotLeft, RollRight, RollLeft;
float RotRate;
ChangeWindowMode( TRUE );
if( DxLib_Init() < 0 )
return -1 ;
ModelHandle = MV1LoadModel( "SimpleModel.mqo" );
SetDrawScreen( DX_SCREEN_BACK );
// カメラの座標を初期化
CameraPos = VGet( 0.0f, 0.0f, -800.0f );
FocusPos = VGet( 0.0f, 0.0f, 0.0f );
HeadDir = VGet( 0.0f, 1.0f, 0.0f );
RotRate = PHI_F * 2.0f / 60.0f;
RotUp = MGetRotX( RotRate );
RotDown = MGetRotX( -RotRate );
RotRight = MGetRotY( -RotRate );
RotLeft = MGetRotY( RotRate );
RollRight = MGetRotZ( -RotRate );
RollLeft = MGetRotZ( RotRate );
while( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{
ClearDrawScreen( );
if( CheckHitKey( KEY_INPUT_SPACE ) == 1 )
{
CameraPos = VGet( 0.0f, 0.0f, -800.0f );
FocusPos = VGet( 0.0f, 0.0f, 0.0f );
HeadDir = VGet( 0.0f, 1.0f, 0.0f );
}
if( CheckHitKey( KEY_INPUT_LSHIFT ) == 0 && CheckHitKey( KEY_INPUT_RSHIFT ) == 0 )
{
if( CheckHitKey( KEY_INPUT_UP ) == 1 )
{
RotUp = MGetRotAxis( VCross( CameraPos, HeadDir ), RotRate );
CameraPos = VTransform( CameraPos, RotUp );
HeadDir = VTransform( HeadDir, RotUp );
}
if( CheckHitKey( KEY_INPUT_DOWN ) == 1 )
{
RotDown = MGetRotAxis( VCross( CameraPos, HeadDir ), -RotRate );
CameraPos = VTransform( CameraPos, RotDown );
HeadDir = VTransform( HeadDir, RotDown );
}
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 )
{
RotLeft = MGetRotAxis( HeadDir, RotRate );
CameraPos = VTransform( CameraPos, RotLeft );
HeadDir = VTransform( HeadDir, RotLeft );
}
if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 )
{
RotRight = MGetRotAxis( HeadDir, -RotRate );
CameraPos = VTransform( CameraPos, RotRight );
HeadDir = VTransform( HeadDir, RotRight );
}
}
else {
if( CheckHitKey( KEY_INPUT_UP ) == 1 )
{
if ( VSize( CameraPos ) > 300.0f )
CameraPos = VScale( CameraPos, 0.95f );
}
if( CheckHitKey( KEY_INPUT_DOWN ) == 1 )
{
if ( VSize( CameraPos ) < 2000.0f )
CameraPos = VScale( CameraPos, 1.05f );
}
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 )
{
RollLeft = MGetRotAxis( CameraPos, RotRate );
HeadDir = VTransform( HeadDir, RollLeft );
}
if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 )
{
RollRight = MGetRotAxis( CameraPos, -RotRate );
HeadDir = VTransform( HeadDir, RollRight );
}
}
SetCameraPositionAndTargetAndUpVec( CameraPos, FocusPos, HeadDir );
DrawLine3D( VGet( 0.0f, 0.0f, 0.0f ), VGet( 1000.0f, 0.0f, 0.0f ), GetColor( 255, 0, 0 ) );
DrawLine3D( VGet( 0.0f, 0.0f, 0.0f ), VGet( 0.0f, 1000.0f, 0.0f ), GetColor( 0, 255, 0 ) );
DrawLine3D( VGet( 0.0f, 0.0f, 0.0f ), VGet( 0.0f, 0.0f, 1000.0f ), GetColor( 0, 0, 255 ) );
MV1DrawModel( ModelHandle );
DrawFormatString( 0, 0, GetColor( 255, 255, 255 ), "CameraPos x=%f y=%f z=%f size=%f", CameraPos.x, CameraPos.y, CameraPos.z, VSize( CameraPos ) );
DrawFormatString( 0, 20, GetColor( 255, 255, 255 ), "FocusPos x=%f y=%f z=%f", FocusPos.x, FocusPos.y, FocusPos.z );
DrawFormatString( 0, 40, GetColor( 255, 255, 255 ), "HeadDir x=%f y=%f z=%f size=%f", HeadDir.x, HeadDir.y, HeadDir.z, VSize( HeadDir ) );
ScreenFlip( );
}
DxLib_End( );
return 0;
}