请问cs中的第一人称视角是怎样实现的?

解决方案 »

  1.   

    不清楚
    但是在delphi里,如果用openGL的话
    只要改变时点就行了
      

  2.   

    在delphi里,如果用的是openGL
    只要改变视点就行了
      

  3.   

    一两句话怎么说的清楚?下个雷神1/2的源代码看看,也有用Object Pascal重写的!
      

  4.   

    Opengl
    印像当中好像是用的Opengllookat()
    但这个函数并不是核心函数,
    而是通过调用诸如平移,旋转之类的函数所构成的。transform,rotate.
      

  5.   

    这个还不简单,你的camera跟到charater走就是了,lookat就不用说了吧一个Z正向vector(右手axis)。
      

  6.   

    看过一本介绍在Delphi下使用opengl的书,后来又看到了一本c++的,完全一样。印象不深刻,等以后用到了再温习一遍吧。书名好像叫《可视化OpenGL开发》吧
      

  7.   

    这里有一个,你看看吧Program OpenGLApp;Uses
       Windows,
       Messages, Dialogs,
       OpenGL,
       SysUtils,
       Textures;Const
       WND_TITLE        = 'OPenGl 演示程序';
       FPS_TIMER        = 1;
       FPS_INTERVAL     = 500;Type
       TCoord = Record
          X, Y, Z: glFLoat;
       End;
       TFace = Record
          V1, V2, V3, V4: Integer;
          U, V: glFloat;
          TextureIndex: Integer;
       End;Var
       h_Wnd            : HWND;
       h_DC             : HDC;
       h_RC             : HGLRC;
       keys             : Array[0..255] Of Boolean;
       FPSCount         : Integer = 0;
       ElapsedTime      : Integer;
       FrameTime        : Integer;   Texture          : Array Of glUint;   TextureCount     : Integer;
       VertexCount      : Integer;
       FaceCount        : Integer;
       Vertex           : Array Of TCoord;
       Face             : Array Of TFace;   X, Z, Y          : glFloat;
       HeadMovement, HeadMovAngle: glFloat;
       mpos             : TPoint;
       Heading          : glFloat;
       Tilt             : glFloat;   MouseSpeed       : Integer = 7;
       MoveSpeed        : glFloat = 0.03;   {$R *.RES}Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external
       opengl32;
    Procedure LoadMap;
    Var
       F                : Textfile;
       Tex              : Array Of String;
       S                : String;
       I, J             : Integer;
    Begin
       AssignFile(F, 'map.txt');
       Reset(F);   Readln(F, TextureCount);
       SetLength(Tex, TextureCount);
       SetLength(Texture, TextureCount);
       For I := 0 To TextureCount - 1 Do
          Begin
             Readln(F, S);
             Tex[i] := Copy(S, 1, Pos(' ', S) - 1);
             S := Copy(S, Pos(' ', S) + 1, length(S));
             LoadTexture(S, Texture[i], FALSE);
          End;   Readln(F, VertexCount);
       SetLength(Vertex, VertexCount);
       For I := 0 To VertexCount - 1 Do
          Readln(F, Vertex[i].X, Vertex[i].Y, Vertex[i].Z);   Readln(F, FaceCount);
       SetLength(Face, FaceCount);
       For I := 0 To FaceCount - 1 Do
          Begin
             Readln(F, Face[i].V1, Face[i].V2, Face[i].V3, Face[i].V4, Face[i].U,
                Face[i].V, S);
             S := Trim(Copy(S, 1, 12));         For J := 0 To TextureCount - 1 Do
                If Tex[J] = S Then
                   Face[i].TextureIndex := J;
          End;
       CloseFile(F);
    End;
      

  8.   

    Procedure glDraw();
    Var
       I                : Integer;
    Begin
       glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT);
       glLoadIdentity();   glRotate(Tilt, 1, 0, 0);
       glRotate(Heading, 0, 1, 0);   glTranslatef(X, -0.5 + HeadMovement, Z);   For I := 0 To FaceCount - 1 Do
          With face[i] Do
             Begin
                glBindTexture(GL_TEXTURE_2D, Texture[TextureIndex]);            glBegin(GL_QUADS);
                glTexCoord(0, 0);
                glVertex3fv(@Vertex[V1 - 1]);
                glTexCoord(U, 0);
                glVertex3fv(@Vertex[V2 - 1]);
                glTexCoord(U, V);
                glVertex3fv(@Vertex[V3 - 1]);
                glTexCoord(0, V);
                glVertex3fv(@Vertex[V4 - 1]);
                glEnd();
             End;
    End;
    Procedure glInit();
    Begin
       glClearColor(0.0, 0.0, 0.0, 0.0);
       glShadeModel(GL_SMOOTH);
       glClearDepth(1.0);
       glEnable(GL_DEPTH_TEST);
       glDepthFunc(GL_LESS);   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   glEnable(GL_TEXTURE_2D);
       LoadMap;   Heading := 180;
       X := 2.25;
       Z := 2;
    End;
    Procedure glResizeWnd(Width, Height: Integer);
    Begin
       If (Height = 0) Then
          Height := 1;   glViewport(0, 0, Width, Height);   glMatrixMode(GL_PROJECTION);
       glLoadIdentity();   gluPerspective(45.0, Width / Height, 0.1, 100.0);   glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();
    End;
    Procedure ProcessKeys;
    Begin
       If Keys[VK_UP] Then
          Begin
             X := X - sin(Heading * pi / 180) * FrameTime / 900;
             Z := Z + cos(Heading * pi / 180) * FrameTime / 900;
             HeadMovAngle := HeadMovAngle + 5;
             HeadMovement := 0.025 * sin(HeadMovAngle * pi / 180);
          End;
       If Keys[VK_DOWN] Then
          Begin
             X := X + sin(Heading * pi / 180) * FrameTime / 900;
             Z := Z - cos(Heading * pi / 180) * FrameTime / 900;
             HeadMovAngle := HeadMovAngle - 5;
             HeadMovement := 0.025 * sin(HeadMovAngle * pi / 180);
          End;
       If Keys[VK_LEFT] Then
          Begin
             X := X + sin((Heading + 90) * pi / 180) * FrameTime / 900;
             Z := Z - cos((Heading + 90) * pi / 180) * FrameTime / 900;
          End;
       If Keys[VK_RIGHT] Then
          Begin
             X := X - sin((Heading + 90) * pi / 180) * FrameTime / 900;
             Z := Z + cos((Heading + 90) * pi / 180) * FrameTime / 900;
          End;
       If Keys[VK_Return] Then
          Begin
             HeadMovAngle := HeadMovAngle - 5;
             HeadMovement := 0.025 * sin(HeadMovAngle * pi / 180);
          End;End;Function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM):
       LRESULT; stdcall;
    Begin
       Result := 0;
       Case (Msg) Of
          WM_CREATE:
             Begin         End;
          WM_CLOSE:
             Begin
                PostQuitMessage(0);
                Result := 0
             End;
          WM_KEYDOWN:
             Begin
                keys[wParam] := True;
                Result := 0;
             End;
          WM_KEYUP:
             Begin
                keys[wParam] := False;
                Result := 0;
             End;
          WM_SIZE:
             Begin
                glResizeWnd(LOWORD(lParam), HIWORD(lParam));
                Result := 0;
             End;
          WM_TIMER:
             Begin
                If wParam = FPS_TIMER Then
                   Begin
                      FPSCount := Round(FPSCount * 1000 / FPS_INTERVAL);
                      SetWindowText(h_Wnd, PChar(WND_TITLE + '   [' +
                         intToStr(FPSCount) + ' 帧/秒]'));
                      FPSCount := 0;
                      Result := 0;
                   End;
             End;
          Else
             Result := DefWindowProc(hWnd, Msg, wParam, lParam);
       End;
    End;
    Procedure glKillWnd(Fullscreen: Boolean);
    Begin
       If Fullscreen Then
          Begin
             ChangeDisplaySettings(devmode(Nil^), 0);
             ShowCursor(True);
          End;
       If h_RC > 0 Then
          If (Not wglMakeCurrent(h_DC, 0)) Then
             MessageBox(0, '释放设备场景句柄失败!', '错误', MB_OK Or
                MB_ICONERROR);   If (Not wglDeleteContext(h_RC)) Then
          Begin
             MessageBox(0, '释放渲染句柄失败!', '错误', MB_OK Or
                MB_ICONERROR);
             h_RC := 0;
          End;   If ((h_DC > 0) And (ReleaseDC(h_Wnd, h_DC) = 0)) Then
          Begin
             MessageBox(0, 'Release of device context failed!', '错误', MB_OK Or
                MB_ICONERROR);
             h_DC := 0;
          End;   If ((h_Wnd <> 0) And (Not DestroyWindow(h_Wnd))) Then
          Begin
             MessageBox(0, '无法销毁窗体!', '错误', MB_OK Or
                MB_ICONERROR);
             h_Wnd := 0;
          End;   If (Not UnRegisterClass('OpenGL', hInstance)) Then
          Begin
             MessageBox(0, '无法注册窗体类!', '错误', MB_OK Or
                MB_ICONERROR);
             hInstance := 0;
          End;
    End;
      

  9.   

    Function glCreateWnd(Width, Height: Integer; Fullscreen: Boolean; PixelDepth:
       Integer): Boolean;
    Var
       wndClass         : TWndClass;
       dwStyle          : DWORD;
       dwExStyle        : DWORD;
       dmScreenSettings : DEVMODE;
       PixelFormat      : GLuint;
       h_Instance       : HINST;
       pfd              : TPIXELFORMATDESCRIPTOR;
    Begin
       h_Instance := GetModuleHandle(Nil);
       ZeroMemory(@wndClass, SizeOf(wndClass));   With wndClass Do
          Begin
             style := CS_HREDRAW Or
             CS_VREDRAW Or
             CS_OWNDC;
             lpfnWndProc := @WndProc;
             hInstance := h_Instance;
             hCursor := LoadCursor(0, IDC_ARROW);
             lpszClassName := 'OpenGL';
          End;   If (RegisterClass(wndClass) = 0) Then
          Begin
             MessageBox(0, '注册窗体类失败!', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit
          End;   If Fullscreen Then
          Begin
             ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings));
             With dmScreenSettings Do
                Begin
                   dmSize := SizeOf(dmScreenSettings);
                   dmPelsWidth := Width;
                   dmPelsHeight := Height;
                   dmBitsPerPel := PixelDepth;
                   dmFields := DM_PELSWIDTH
                   Or DM_PELSHEIGHT
                   Or DM_BITSPERPEL;
                End;         If (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN) =
                DISP_CHANGE_FAILED) Then
                Begin
                   MessageBox(0, '不能转换为全屏模式!', '错误', MB_OK
                      Or
                      MB_ICONERROR);
                   Fullscreen := False;
                End;
          End;   If (Fullscreen) Then
          Begin
             dwStyle := WS_POPUP Or
             WS_CLIPCHILDREN
             Or WS_CLIPSIBLINGS;
             dwExStyle := WS_EX_APPWINDOW;
             ShowCursor(False);
          End
       Else
          Begin
             dwStyle := WS_OVERLAPPEDWINDOW Or
             WS_CLIPCHILDREN Or
             WS_CLIPSIBLINGS;
             dwExStyle := WS_EX_APPWINDOW Or
             WS_EX_WINDOWEDGE;
             ShowCursor(false);
          End;   h_Wnd := CreateWindowEx(dwExStyle,
          'OpenGL',
          WND_TITLE,
          dwStyle,
          0, 0,
          Width, Height,
          0,
          0,
          h_Instance,
          Nil);
       If h_Wnd = 0 Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '不能创建窗体!', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit;
          End;   With pfd Do
          Begin
             nSize := SizeOf(TPIXELFORMATDESCRIPTOR);
             nVersion := 1;
             dwFlags := PFD_DRAW_TO_WINDOW
             Or PFD_SUPPORT_OPENGL
             Or PFD_DOUBLEBUFFER;
             iPixelType := PFD_TYPE_RGBA;
             cColorBits := PixelDepth;
             cRedBits := 0;
             cRedShift := 0;
             cGreenBits := 0;
             cGreenShift := 0;
             cBlueBits := 0;
             cBlueShift := 0;
             cAlphaBits := 0;
             cAlphaShift := 0;
             cAccumBits := 0;
             cAccumRedBits := 0;
             cAccumGreenBits := 0;
             cAccumBlueBits := 0;
             cAccumAlphaBits := 0;
             cDepthBits := 16;
             cStencilBits := 0;
             cAuxBuffers := 0;
             iLayerType := PFD_MAIN_PLANE;
             bReserved := 0;
             dwLayerMask := 0;
             dwVisibleMask := 0;
             dwDamageMask := 0;
          End;   h_DC := GetDC(h_Wnd);
       If (h_DC = 0) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '不能得到设备场景!', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit;
          End;   PixelFormat := ChoosePixelFormat(h_DC, @pfd);
       If (PixelFormat = 0) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '找不到合适的格式', '错误', MB_OK
                Or MB_ICONERROR);
             Result := False;
             Exit;
          End;   If (Not SetPixelFormat(h_DC, PixelFormat, @pfd)) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '无法创建渲染格式', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit;
          End;   h_RC := wglCreateContext(h_DC);
       If (h_RC = 0) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '无法创建OpenGL 绘制描述表', '错误',
                MB_OK Or MB_ICONERROR);
             Result := False;
             Exit;
          End;
       If (Not wglMakeCurrent(h_DC, h_RC)) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error',
                MB_OK Or MB_ICONERROR);
             Result := False;
             Exit;
          End;   SetTimer(h_Wnd, FPS_TIMER, FPS_INTERVAL, Nil);   ShowWindow(h_Wnd, SW_SHOW);
       SetForegroundWindow(h_Wnd);
       SetFocus(h_Wnd);   glResizeWnd(Width, Height);
       glInit();   Result := True;
    End;
    Function WinMain(hInstance: HINST; hPrevInstance: HINST;
       lpCmdLine: PChar; nCmdShow: Integer): Integer; stdcall;
    Var
       msg              : TMsg;
       finished         : Boolean;
       DemoStart, LastTime: DWord;
    Begin
       finished := False;   If Not glCreateWnd(800, 600, false, 32) Then
          Begin
             Result := 0;
             Exit;
          End;   DemoStart := GetTickCount();
       SetCursorPos(400, 300);   While Not finished Do
          Begin
             If (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) Then            Begin
                   If (msg.message = WM_QUIT) Then
                      finished := True
                   Else
                      Begin
                         TranslateMessage(msg);
                         DispatchMessage(msg);
                      End;
                End
             Else
                Begin
                   Inc(FPSCount);               FrameTime := GetTickCount() - ElapsedTime - DemoStart;
                   LastTime := ElapsedTime;
                   ElapsedTime := GetTickCount() - DemoStart;
                   ElapsedTime := (LastTime + ElapsedTime) Div 2;               If GetForegroundWindow = h_Wnd Then
                      Begin
                         GetCursorPos(mpos);
                         SetCursorPos(400, 300);
                         Heading := Heading + (mpos.x - 400) / 100 * MouseSpeed;
                         Tilt := Tilt - (300 - mpos.y) / 100 * MouseSpeed;
                         If Tilt > 60 Then
                            Tilt := 60;
                         If Tilt < -60 Then
                            Tilt := -60;
                      End;               glDraw();
                   SwapBuffers(h_DC);               If (keys[VK_ESCAPE]) Then
                      finished := True
                   Else
                      ProcessKeys;
                End;
          End;
       glKillWnd(FALSE);
       Result := msg.wParam;             
    End;Begin
       WinMain(hInstance, hPrevInst, CmdLine, CmdShow);
    End.
      

  10.   

    阿德说得没错 他的这个例子 就是一个主视角的demo http://expert.csdn.net/Expert/topic/2072/2072933.xml?temp=.1717646有兴趣到这里讨论把
      

  11.   

    呵呵
    阿德的例子没有错的啦,就是一个主视角的demo
    所以……up啦