游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2368|回复: 7

求教高手如何让摄象机在原地坐自我旋转.

[复制链接]

23

主题

68

帖子

68

积分

注册会员

Rank: 2

积分
68
发表于 2006-3-28 00:14:00 | 显示全部楼层 |阅读模式
我发现当我把摄像机移动到球面天空的紧左边或紧右边后,我旋转摄像机,发现他不是按照自己内部的y轴转,而是按照屏幕中心的那个y轴旋转,我想让他在原地做自我旋转,而不是围着屏幕饶大圈,请问应该怎样??谢谢..
我的旋转代码如下:
D3DXMATRIX matRotate;
        D3DXMatrixRotationY(&matRotate,fAngle);
        D3DXVec3TransformCoord(&eye,&eye,&matRotate);
        D3DXVec3TransformCoord(&at,&at,&matRotate);
        D3DXVec3TransformCoord(&right,&right,&matRotate);
        D3DXVec3TransformCoord(&up,&up,&matRotate);
顺便说一下我移动摄象机是 视线和视点同时移动和旋转的.我想达到cs的移动效果.

9

主题

198

帖子

198

积分

注册会员

Rank: 2

积分
198
发表于 2006-3-28 00:31:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

D3DXVec3TransformCoord(&eye,&eye,&matRotate);??为什么做这样的变换?
你再好好想象,这个问题不是很难。

27

主题

409

帖子

440

积分

中级会员

Rank: 3Rank: 3

积分
440
QQ
发表于 2006-3-28 16:04:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

看光线游戏引擎的示例源代码吧,或许对你有帮助:

#include "main.h"

player_t   player;

// 初始化玩家信息
int InitialPlayer( void )
{
        char string[MAX_PATH];
        int num, p = 0;
       
        //num = gGetMapStringNumber( 0 );
        //sprintf( string, "实体数:%d", num );
        gGetMapString( string, "origin", 3, 0 );
        player.pos[0] = atof( &string[p] );
        while( string[p++] != ' ' );
        player.pos[1] = atof( &string[p] );
        while( string[p++] != ' ' );
        player.pos[2] = atof( &string[p] );
        player.rotate[0] = 0;
        player.rotate[1] = 0;
        player.mouse_speed = 500;
        player.viewline = 150;
        player.forward = 0;
        player.right = 0;
        player.move = 0;
        player.velocity = (float)250/1000;
        player.sequence = 1;
        //////////////////////
        // 防止地面摩擦
        player.pos[2] +=5;
        //////////////////////

        // 将骨骼动画文件读入内存
        player.model  = gLoadModel( "..\\resource\\girl.mdl" );
        if ( player.model < 0 )
                return 1;
        // 设置模型动作
        gSetModelSequence( player.model, 1 );
        // 设置模型位置
        gSetModelPos( player.model, player.pos[0], player.pos[1], player.pos[2] );
        // 设置模型旋转角度
        //gSetModelRotate( player.model, 270, 0, 0 );
        player.step[0] = gLoadSound( "..\\resource\\pl_step1.wav" );
        player.step[1] = gLoadSound( "..\\resource\\pl_step2.wav" );
        player.step[2] = gLoadSound( "..\\resource\\pl_step3.wav" );
        player.step[3] = gLoadSound( "..\\resource\\pl_step4.wav" );
        player.m4a1[0] = gLoadSound( "..\\resource\\m4a1_unsil-2.wav" );
        gSetSoundMinDistance( player.step[1], 50 );
        gSetSoundMinDistance( player.m4a1[0], 100 );

        // 读取弹痕纹理
        player.crater[0] = gLoadImage( "..\\resource\\temp16-rle.tga" );
        player.crater[1] = gLoadImage( "..\\resource\\crater2.bmp" );
        player.crater[2] = gLoadImage( "..\\resource\\crater3.bmp" );
        player.crater[3] = gLoadImage( "..\\resource\\crater4.bmp" );

        return 0;
}

// 处理玩家输入
int InputPlayer( void )
{
        POINT point;
        int x, y, cx, cy;
        double rotate[3];
        float xy;
        vec3_t upright;

        gGetCursorPos( &point );       
        cx = 400;
        cy = 300;
        gSetCursorPos( cx, cy );
        x = point.x - cx;
        y = point.y - cy;       
        rotate[0] = player.rotate[0] + (float)x / player.mouse_speed;
        rotate[1] = player.rotate[1] - (float)y / player.mouse_speed;

        if( rotate[0] > 2 * G_PI )
                rotate[0] -= 2 * G_PI;
        if( rotate[0] < 0 )
                rotate[0] += 2 * G_PI;
        /*if( rotate[1] > 0.5 * G_PI )
                rotate[1] = 0.5 * G_PI;
        if( rotate[1] < - 0.5 * G_PI )
                rotate[1] = - 0.5 * G_PI;*/       
        if( rotate[1] > 0.075 * G_PI )
                rotate[1] = 0.075 * G_PI;
        if( rotate[1] < -0.5 * G_PI )
                rotate[1] = -0.5 * G_PI;
       
        //xy = (float)cos( rotate[1] );
        //player.eyes[0] = (float)sin( rotate[0] ) * xy;
        //player.eyes[1] = (float)cos( rotate[0] ) * xy;
        //player.eyes[2] = (float)sin( rotate[1] );
        xy = (float)cos( rotate[1] ) * player.viewline;
        player.eyes[0] = -(float)sin( rotate[0] ) * xy;
        player.eyes[1] = -(float)cos( rotate[0] ) * xy;
        player.eyes[2] = -(float)sin( rotate[1] ) * player.viewline;
        player.direction[0] = (float)sin( rotate[0] );
        player.direction[1] = (float)cos( rotate[0] );
        player.direction[2] = 0;

        upright[0] =   player.eyes[1];
        upright[1] = - player.eyes[0];       
        upright[2] =   0;
        gCrossProduct( upright, player.eyes, player.up );

        // 移动玩家
        int time;
        float s, temp;
        vec3_t vects, sv;
        vec3_t p1;

        time = gGetTickCount();
        if( player.forward || player.right )
        {
                // 保存玩家原来坐标
                gVectorCopy ( player.pos, p1 );

                s = (float)player.velocity * ( time - player.lasttime );
                sv[0] = (float)player.right;
                sv[1] = (float)player.forward;
                sv[2] = 0;

                gVectorNormalize( sv );
                gVectorScale( sv, s, sv );

                // forward 产生的位移
                //gVectorScale( player.eyes, sv[1], vects );
                gVectorScale( player.direction, sv[1], vects );
                gVectorAdd( player.pos, vects, player.pos );
                // right 产生的位移
                gVectorCopy( player.direction, vects );
                temp = vects[0]; // 向量旋转 -90 度
                vects[0] = vects[1];
                vects[1] = -temp;
                gVectorNormalize( vects );
                //gVectorScale( vects, sv[0], vects );
                gVectorScale( vects, sv[0] * 0.4, vects );
                gVectorAdd( player.pos, vects, player.pos );

                // 进行碰撞检测,并计算碰撞后坐标
                gModelCollideMap ( p1, player.pos, player.model, 0 );
                // 设置模型动作
                if ( player.sequence != 4 )
                {
                        player.sequence = 4;
                        gSetModelSequence( player.model, 4 );                       
                }
                // 播放脚步声
                if( time - player.steptime > 300 )
                {
                        gSetSoundPos( player.step[1], player.pos[0], player.pos[1], player.pos[2] );
                        gPlaySound( player.step[1] );
                        player.steptime = time;
                }
        }
        else
        {
                // 设置模型动作
                if ( player.sequence != 1 )
                {
                        player.sequence = 1;
                        gSetModelSequence( player.model, 1 );                       
                }
        }
        // 射击处理
        if( player.shoot )
        {
                if( time - player.shoottime > 100 )
                {
                        gSetSoundPos( player.m4a1[0], player.pos[0], player.pos[1], player.pos[2] );
                        gPlaySound( player.m4a1[0] );
                        player.shoottime = time;
                }
        }

        player.lasttime = time;

        player.eyes[0] += player.pos[0];
        player.eyes[1] += player.pos[1];
        player.eyes[2] += player.pos[2];
       
        player.rotate[0] = rotate[0];
        player.rotate[1] = rotate[1];

        return 0;
}

// 场景漫游演示程序
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
        unsigned int key;
        float angle;
        int model1;
        float a[3][4], b[3][4], c[3][4];
               
        // 启动光线游戏引擎
        gLightStartup();
        // 设置显示模式为窗口模式
        //gSetWindowMode(200, 150, 400, 300, 0);
        gSetDisplayMode( 0, 0, 0, 0, 0 );
        gInitialInput();
        gInitialSound();
        gSetColorKey( 255, 0, 0 );
        gEnable( G_COLOR_KEY );
       
        // 显示正在读取资料的提示信息
        gColor( 0, 255, 0 );
        gSetTextPos( 290, 280 );
        gDrawText( "正在读取资料,请稍候......" );
        gUpdateDisplay();

        // 读取地图文件
        gLoadMap( "..\\resource\\cs_bloodstrike.bsp" );
        gOpenVideo( "..\\resource\\back.mp3" );
        //gVideoPlay();
        // 读取挖掘机模型
        vec3_t pos;
        int p = 0;
        char string[100];
        model1 = gLoadModel( "..\\resource\\w_m4a1.mdl" );
        gGetMapString( string, "origin", 9, 0 );
        pos[0] = atof( &string[p] );
        while( string[p++] != ' ' );
        pos[1] = atof( &string[p] );
        while( string[p++] != ' ' );
        //pos[2] = atof( &string[p] ) - 35;
        pos[2] = atof( &string[p] );
        gSetModelPos( model1, pos[0], pos[1], pos[2] );
        //gSetModelPos( model1, 0, 0, 0 );
        // 设置模型矩阵
        gRotateXMatrix( 90, a );       
        gRotateZMatrix( 270, b );
        gMultiplyMatrix( a, b, c );       
        gRotateYMatrix( 340, a );
        gMultiplyMatrix( a, c, b );       
        pos[0] = 11;
        pos[1] = 0;
        pos[2] = 0;
        gTranslateMatrix( pos, a );
        gMultiplyMatrix( a, b, c );       
        gSetModelMatrix( model1, c );
       
        // 初始化玩家信息
        InitialPlayer();
        // 将武器绑定到玩家身上
        gAttachmentModel( model1, player.model, 0 );

        ShowCursor( TRUE );
        gSetCursorPos( 400, 300 );

        // 计算弹痕多边形
        vertex_t vertex[4];
               
        gVectorCopy( player.pos, vertex[0].vertex );
        gVectorCopy( player.pos, vertex[1].vertex );
        gVectorCopy( player.pos, vertex[2].vertex );
        gVectorCopy( player.pos, vertex[3].vertex );
        vertex[1].vertex[0] += 50;
        vertex[2].vertex[0] += 50;
        vertex[2].vertex[2] -= 50;
        vertex[3].vertex[2] -= 50;
        for( int i=0; i<4; i++ )
        {
                vertex.normal[0] =  0;
                vertex.normal[1] = -1;
                vertex.normal[2] =  0;
        }
        vertex[0].texcoord[0] = 0;
        vertex[0].texcoord[1] = 0;
        vertex[1].texcoord[0] = 1;
        vertex[1].texcoord[1] = 0;
        vertex[2].texcoord[0] = 1;
        vertex[2].texcoord[1] = 1;
        vertex[3].texcoord[0] = 0;
        vertex[3].texcoord[1] = 1;

        // 设置听众位置
        gSetListenerPos( player.pos[0], player.pos[1], player.pos[2] );
        // 设置距离因子
        //gSetRolloffFactor( 0.035 );
                                   
        do
        {        // 清除屏幕内容
                gClearDisplay();

                // 设置摄像机位置               
                gLookAt( player.eyes[0], player.eyes[1], player.eyes[2],
                             player.pos[0],  player.pos[1],  player.pos[2] + 50,                             
                                 player.up[0], player.up[1], player.up[2] );
                // 显示地图
                gDrawMap( 0 );
               
                // 设置模型位置
                gSetModelPos( player.model, player.pos[0], player.pos[1], player.pos[2] );
                // 设置模型旋转角度
                //angle = player.rotate[0] * (( float)180 / G_PI ) + 270;
                angle = 360 - (player.rotate[0] * (( float)180 / G_PI )) + 90;
                gSetModelRotate( player.model, angle, 0, 0 );
                               
                // 显示骨骼动画
                gDrawModel( player.model );
                gDrawModel( model1 );

                // 显示弹痕多边形
                //gEnable( G_BLEND );
                //gPolygon( vertex, 4, player.crater[0] );
                //gDisable( G_BLEND );

                // 显示布告板
                gBillboard( vertex[0].vertex, 50, 50, player.crater[0] );
                //gParticle( vertex[0].vertex, 50, 50, player.crater[0] );
               
                // 处理玩家指令
                InputPlayer();

                // 碰撞检测
                /*vec3_t vert[2], cross;
                vert[0][0] = player.pos[0] + player.direction[0] * 50;
                vert[0][1] = player.pos[1] + player.direction[1] * 50;
                vert[0][2] = player.pos[2] + player.direction[2] * 50;
                vert[1][0] = player.pos[0];
                vert[1][1] = player.pos[1];
                vert[1][2] = player.pos[2];
                gColor( 255, 0, 0 );
                gLines( vert, 2 );
                gColor( 0, 255, 0 );
                if( gLineCrossMap( vert[0], vert[1], cross ) )
                {
                        gPoints( &cross, 1 );
                        //MessageBox( 0, "", "", MB_OK );
                }*/
                                       
                // 显示帧速(FPS)
                char fps[100];
                sprintf( fps, "帧速: %d 帧/秒", gGetFramePerSecond() );
                gColor( 0, 255, 0 );
                gSetTextPos( 40, 550 );               
                gDrawText( fps );
                sprintf( fps, "\"光线游戏引擎\"演示", gGetFramePerSecond() );
                gSetTextPos( 500, 490 );               
                gDrawText( fps );
                sprintf( fps, "http://light.gameres.com", gGetFramePerSecond() );
                gSetTextPos( 500, 520 );               
                gDrawText( fps );
                sprintf( fps, "按键:W S A D 和 鼠标左键", gGetFramePerSecond() );
                gSetTextPos( 500, 550 );               
                gDrawText( fps );

                // 显示准星
                gLineRaster( 390,300, 395,300);
                gLineRaster( 405,300, 410,300);
                gLineRaster( 400,290, 400,295);
                gLineRaster( 400,305, 400,310);

                // 更新显示
                gUpdateDisplay();

                // 读取按键信息
                player.forward = 0;
                player.right = 0;
                player.shoot = 0;
                key = gGetKey();
                if( gGetKeyState( KEY_W ) )
                        player.forward = 1;
                else
                if( gGetKeyState( KEY_S ) )
                        player.forward = -1;
                if( gGetKeyState( KEY_A ) )
                        player.right = -1;
                else
                if( gGetKeyState( KEY_D ) )
                        player.right = 1;
                if( gGetKeyState( KEY_MOUSE_BUTTON0 ) )
                        player.shoot = 1;
        }
        // 配送消息
        while( key != KEY_ESCAPE && gDispatchMessage() );

        gCloseVideo();
        // 从内存中释放地图文件
        gUnloadMap( 0 );
        // 从内存中释放模型文件
        gUnloadModel( player.model );

        // 退出光线游戏引擎
        gLightCleanup();
       
        return 0;
}

23

主题

68

帖子

68

积分

注册会员

Rank: 2

积分
68
 楼主| 发表于 2006-3-28 21:43:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

我把D3DXVec3TransformCoord(&eye,&eye,&matRotate)去了以后,虽然原地旋转但是出现了,坐标轴没有改变的问题,它按原先的坐标轴移动了 但是我已经D3DXVec3TransformCoord(&right,&right,&matRotate);了呀!!不知道为什么!!

7

主题

299

帖子

305

积分

中级会员

Rank: 3Rank: 3

积分
305
发表于 2006-3-29 01:07:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

你这段代码是错误的,如果你是要原地旋转的话

D3DXVec3TransformCoord(&eye,&eye,&matRotate),这个绝对错的,既然你是原地旋转干嘛
还要转换摄像机的位置呢??

以下是我做过的摄像机类的一段原地转的代码,现在用在我的半条命地图观察器:

        D3DXVECTOR3                LookAtPoint;
        D3DXVECTOR3                pos;
        D3DXVECTOR3                Right;
        D3DXVECTOR3                Look;
        D3DXVECTOR3                Up;

        pos = GetEyePt(); //得到摄像机位置
        LookAtPoint = GetLookatPt();
        Up = GetUpVec(); //正上方
        Right = GetCross(); //摄像机右方
        Look = LookAtPoint - pos;//摄像机观察的点减摄像机坐标,等于摄像机的正前方向
        D3DXVec3Normalize(&Look,&Look);

        D3DXMATRIX T;

        D3DXMatrixRotationY(&T, angle);
        Right.y = 0;
        D3DXVec3Normalize(&Right,&Right);

        // rotate _right and _look around _up or y-axis
                //旋转正前和正右轴
        D3DXVec3TransformCoord(&Right,&Right, &T);
        D3DXVec3TransformCoord(&Look,&Look, &T);
        //normalizes
    D3DXVec3Cross( &Up, &Right, &Look );
        D3DXVec3Normalize(&Up,&Up);
        D3DXVec3Cross( &Look, &Up, &Right );
        D3DXVec3Normalize(&Look,&Look);

        //reset params of view in the basic class D3DCamera
         D3DXMatrixLookAtLH( &m_matView, &pos, &(pos+Look), &Up );


35

主题

59

帖子

65

积分

注册会员

Rank: 2

积分
65
发表于 2006-3-29 19:43:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

D3DXVECTOR3 vEyePt( eyePos.x-sinf(angle)*rho,eyePos.y+5,eyePos.z-cosf(angle)*rho);
D3DXVECTOR3 vLookatPt(eyePos.x,eyePos.y,eyePos.z );
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
device->SetTransform( D3DTS_VIEW, &matView );

angle是旋转的角度,

38

主题

275

帖子

281

积分

中级会员

Rank: 3Rank: 3

积分
281
QQ
发表于 2006-4-22 15:21:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

   我自己有个思路,不知道可以不可以.(实验的时候有点问题,但是不知道是不是这里的问题)
  我让摄象机的look at position 围绕着它的 eye position 所在的垂直于xz平面的轴转动.
          D3DXMatrixTranslation(&mat_tran,g_ep.x,0,g_ep.z);        //global eye position       
        D3DXMatrixRotationY(&mat_y,angle);                                D3DXMatrixMultiply(&mat_tran,&mat_tran,&mat_y);               
        D3DXVec3TransformCoord(&g_lp,&g_lp,&mat_tran); //global look at position
即到达了旋转 look at position 这个点的目的,然后重新设置观察转换矩阵.
不知道这个方法正确不正确?(我实验了,结果好象不稳定,有时候可以有时候又不可以,我怀疑这个方法正确,但是在程序的其他地方有错误!高手帮忙指正一下)

0

主题

25

帖子

29

积分

注册会员

Rank: 2

积分
29
发表于 2006-4-23 18:40:00 | 显示全部楼层

Re:求教高手如何让摄象机在原地坐自我旋转.

                D3DXMATRIX T;

        // 总是围绕 y (0, 1, 0) 旋转
        // 创建一个绕y轴旋转了angle角度的矩阵T
        D3DXMatrixRotationY(&T, angle);

        // 围绕 _up 或 y-轴旋转  _right and _look  向量
        // 由给定的一个矩阵来变换一个3D向量
        D3DXVec3TransformCoord(&_right,&_right, &T);
        D3DXVec3TransformCoord(&_look,&_look, &T);
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 07:04

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表