Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

OpenGL camera demonstration

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • OpenGL camera demonstration

    Code:
    '
    ' This little program is a demo of OpenGL's GluLookAt function, which is like a camera
    ' that you can orient at any angle to view a 3D world.
    ' Use the arrow keys to rotate the camera up, down, left, or right.
    ' Use "A" or "S" to spin the camera
    ' Use "Z" or "X" to move ahead or backwards.
    ' You'll need the OpenGL Include files to compile this program.  There's a link to these
    ' files somewhere on the PowerBasic website.
    '
    ' I just started to get into OpenGL a couple weeks ago and quickly realized that to program
    ' a 3D world you need to know some math.  More than what knew to program my game
    ' POLYGON WAR in which the game takes place on a plane but is flipped perpendicular to the
    ' monitor to give depth perception.
    ' So I educated myself by looking at the camera
    ' tutorials at www.gametutorials.com  and so here's my first program in OpenGL.
    '
    ' Joel Patterson        www.spiritone.com\~joeltr 
    
    #COMPILE EXE "ROCKS"
    #INCLUDE "WIN32API.INC"
    #INCLUDE "GL.INC"
    #INCLUDE "GLU.INC"
    #INCLUDE "GLAUX.INC"
    
    %rocks=1000
    
    $classname="Spinning cubes in true 3D space."
    
    FUNCTION WINMAIN (BYVAL hInstance  AS LONG,_
                      BYVAL hPrevInstance AS LONG,_
                      lpCmdLine           AS ASCIIZ PTR,_
                      BYVAL iCmdShow      AS LONG) AS LONG
    
    
        DIM Xcube(%rocks) AS GLOBAL SINGLE
        DIM Ycube(%rocks) AS GLOBAL SINGLE
        DIM Zcube(%rocks) AS GLOBAL SINGLE
        DIM XcubeAngle(%rocks) AS GLOBAL SINGLE
        DIM YcubeAngle(%rocks) AS GLOBAL SINGLE
        DIM ZcubeAngle(%rocks) AS GLOBAL SINGLE
        DIM CubeSize(%rocks) AS GLOBAL SINGLE
    
        GLOBAL Xposition AS SINGLE    'Position of your Camera
        GLOBAL Yposition AS SINGLE
        GLOBAL Zposition AS SINGLE
    
        GLOBAL Xview AS SINGLE        'Direction of your Camera
        GLOBAL Yview AS SINGLE
        GLOBAL Zview AS SINGLE
    
        GLOBAL Xup AS SINGLE          'Up Vector
        GLOBAL Yup AS SINGLE
        GLOBAL Zup AS SINGLE
    
        GLOBAL Xhorz AS SINGLE        'Horizontal vector.
        GLOBAL Yhorz AS SINGLE
        GLOBAL Zhorz AS SINGLE
    
        GLOBAL Xdir AS SINGLE         'Direction of movement
        GLOBAL Ydir AS SINGLE
        GLOBAL Zdir AS SINGLE
    
        GLOBAL XvVector AS SINGLE     'Temporary vector.
        GLOBAL YvVector AS SINGLE
        GLOBAL ZvVector AS SINGLE
    
        GLOBAL XvAxis AS SINGLE       'Arbitrary axis to move around.
        GLOBAL YvAxis AS SINGLE
        GLOBAL ZvAxis AS SINGLE
    
        GLOBAL Magnitude AS SINGLE
    
    
        GLOBAL Msg      AS tagMsg
        LOCAL wce      AS WndClassEx
        LOCAL szClassName AS ASCIIZ*80
        GLOBAL hWnd     AS DWORD
        LOCAL htimer   AS DWORD
        LOCAL myclass  AS STRING
    
        RANDOMIZE TIMER
        szClassName=$ClassName
    
        wce.cbSize  =  SIZEOF(wce)
        wce.style  =  %null
        wce.lpfnWndProc  =  CODEPTR(WndPRoc)
        wce.cbClsExtra  =  0
        wce.cbWndExtra  =  0
        wce.hInstance  =  hInstance
        wce.hIcon  =  LoadIcon(hInstance,"PROGRAM")
        wce.hCursor  =  0
        wce.hbrBackground  =  %NULL
        wce.lpszMenuName  =  %NULL
        wce.lpszClassName  =  VARPTR(szclassname)
        wce.hIconSm  =  LoadIcon(hInstance,BYVAL %IDI_APPLICATION)
    
        RegisterClassEx wce
    
        hWnd=CreateWindowEx(%ws_ex_appwindow,_            'the fullscreen window
                            $classname,_
                            $classname,_
                            %ws_overlappedwindow OR %ws_visible,_
                            0,_
                            0,_
                            640,_
                            480,_
                            %hwnd_desktop,_
                            BYVAL 0,_
                            hInstance,_
                            BYVAL %NULL)
    
    
        showwindow hWnd, %sw_normal
        UpdateWindow hWnd
    
        DO WHILE PeekMessage(Msg, %NULL, 0, 0, %PM_NOREMOVE)
          IF GetMessage(Msg, %NULL, 0, 0) THEN
            TranslateMessage Msg
            DispatchMessage Msg
          ELSE
            EXIT FUNCTION
          END IF
        LOOP
    
        FUNCTION = msg.wParam
    
    END FUNCTION
    
    
    FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG,_
                        BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
    
    
          STATIC holdpen AS DWORD
          GLOBAL PS AS paintstruct
          LOCAL t AS DWORD              'looping variables.
          LOCAL temp AS SINGLE
          LOCAL temp2 AS SINGLE
          LOCAL T1 AS INTEGER
          LOCAL t2 AS INTEGER
          GLOBAL hdc AS DWORD
          GLOBAL g_hdc AS LONG
          GLOBAL Hrc AS LONG
          GLOBAL wid AS SINGLE,hei AS SINGLE
          LOCAL lp AS LONG
    
       SELECT CASE wMsg
    
        CASE %WM_CREATE
          hdc=getdc(hwnd)
          g_hdc=hdc
          CALL setupPixelFormat(hdc)
          Hrc=wglCreateContext(hdc)
          wglMakeCurrent hdc,hrc
    
          Xposition=0     'Initial Position of camera.
          Yposition=0
          Zposition=0
    
          Xview=0         'Initial Direction of camera.
          Yview=0
          Zview=-1
    
          Xup=0:Yup=1:Zup=0     'Initial Up Position of camera.
    
    
          glpointsize 1
          glenable %gl_point_smooth
          glenable %gl_cull_face
          glcullface %gl_back
          glfrontface %gl_ccw
          glenable %gl_depth_test
    
    
          FOR lp=0 TO %rocks           'Initial position of cubes
              Xcube(lp)=RND(-1000,1000)
              Ycube(lp)=RND(-1000,1000)
              Zcube(lp)=RND(-1000,1000)
              XcubeAngle(lp)=RND(0,359)
              YcubeAngle(lp)=RND(0,359)
              ZcubeAngle(lp)=RND(0,359)
              CubeSize(lp)=RND(1,30)
          NEXT lp
    
          EXIT FUNCTION
    
         CASE %WM_PAINT
    
             CALL DoGraphics()
             EXIT FUNCTION
    
         CASE %WM_CLOSE
             wglMakeCurrent hdc,%null
             wglDeleteContext hrc
    
             PostQuitMessage 0
             EXIT FUNCTION
    
         CASE %WM_SYSCOMMAND
             IF wparam=%sc_close THEN
                 postquitmessage 0
             END IF
    
         CASE %wm_size
             wid=LOWRD(lparam)
             hei=HIWRD(lparam)
    
             glviewport 0,0,wid,hei
             glmatrixmode %gl_projection
             glloadidentity
    
             gluperspective 45,wid/hei,1,2000
             glmatrixmode %gl_modelview
             glloadidentity
             EXIT FUNCTION
    
         CASE %WM_DESTROY                   'Exit back to windows.
    
             PostQuitMessage 0
             EXIT FUNCTION
    
    
       END SELECT
       FUNCTION=DefWindowProc(hWnd,wMsg,wParam,lParam)
    
    END FUNCTION
    
    
    SUB setuppixelformat(BYVAL hdc AS DWORD)
    
        GLOBAL PP AS pixelformatdescriptor
        GLOBAL Npixelformat AS DWORD
    
        PP.nsize =SIZEOF(PP)
        pp.nversion =1
        pp.dwflags =%pfd_draw_to_window OR %pfd_support_opengl OR %pfd_doublebuffer
        pp.ipixeltype =%pfd_type_rgba
        pp.ccolorbits =32
        pp.credbits =0
        pp.credshift =0
        pp.cgreenbits =0
        pp.cgreenshift =0
        pp.cbluebits =0
        pp.cblueshift =0
        pp.calphabits =0
        pp.calphashift =0
        pp.caccumbits =0
        pp.caccumredbits =0
        pp.caccumgreenbits =0
        pp.caccumbluebits =0
        pp.caccumalphabits =0
        pp.cdepthbits =16
        pp.cstencilbits =0
        pp.cauxbuffers =0
        pp.ilayertype =%pfd_main_plane
        pp.breserved =0
        pp.dwlayermask =0
        pp.dwvisiblemask =0
        pp.dwdamagemask =0
    
        npixelformat=ChoosePixelFormat(hdc,PP)
        SetpixelFormat hdc,npixelformat,PP
    
    END SUB
    '
    '  *Set Camera and draw spinning cubes.
    '
    SUB DoGraphics
    
        LOCAL t AS DWORD
        LOCAL temp AS SINGLE
        LOCAL temp2 AS SINGLE
        LOCAL lp AS LONG
    
    
        CALL GetKeyboard
    
        glclear %gl_color_buffer_bit OR %gl_depth_buffer_bit
        glloadIdentity
        gluLookAt Xposition,Yposition,Zposition,_
                  Xview,Yview,Zview,Xup,Yup,Zup
    
        FOR lp=0 TO %rocks
          XcubeAngle(lp)=XcubeAngle(lp)+0.5
          IF Xcubeangle(lp)>360 THEN Xcubeangle(lp)=0
          Ycubeangle(lp)=Ycubeangle(lp)+1
          IF Ycubeangle(lp)>360 THEN Ycubeangle(lp)=0
          Zcubeangle(lp)=Zcubeangle(lp)+1.5
          IF Zcubeangle(lp)>360 THEN Zcubeangle(lp)=0
    
    
          CALL DrawCube(Xcube(lp),Ycube(lp),Zcube(lp),_
                        Xcubeangle(lp),Ycubeangle(lp),Zcubeangle(lp),_
                        cubesize(lp))
        NEXT lp
    
        swapbuffers g_hdc
    END SUB
    '
    ' * Draw a cube oriented at any angle
    '
    SUB DrawCube(BYVAL Xpos AS SINGLE,BYVAL Ypos AS SINGLE,BYVAL Zpos AS SINGLE,_
                 BYVAL Xangle AS SINGLE,BYVAL Yangle AS SINGLE,BYVAL Zangle AS SINGLE,_
                 BYVAL big AS SINGLE)
    
         glpushmatrix
         gltranslatef Xpos,Ypos,Zpos   'Position the cube
         glrotatef Xangle,1,0,0        'Rotate around X axis
         glrotatef Yangle,0,1,0        'Rotate around Y axis
         glrotatef Zangle,0,0,1        'Rotate around Z axis
         glscalef big,big,big          'Size of cube
         glbegin %gl_quads
            glcolor3f 1,1,1
            glvertex3f -0.5,-0.5,0.5     'front face
            glvertex3f 0.5,-0.5,0.5
            glvertex3f 0.5,0.5,0.5
            glvertex3f -0.5,0.5,0.5
         glend
         glbegin %gl_quads
            glcolor3f 1,0.5,1
            glvertex3f -0.5,-0.5,-0.5   'back face
            glvertex3f -0.5,0.5,-0.5
            glvertex3f 0.5,0.5,-0.5
            glvertex3f 0.5,-0.5,-0.5
         glend
         glbegin %gl_quads
            glcolor3f 0.5,1,1
            glvertex3f 0.5,-0.5,0.5   'right face
            glvertex3f 0.5,-0.5,-0.5
            glvertex3f 0.5,0.5,-0.5
            glvertex3f 0.5,0.5,0.5
         glend
         glbegin %gl_quads
            glcolor3f 1,1,0.5
            glvertex3f -0.5,-0.5,0.5  'left face
            glvertex3f -0.5,0.5,0.5
            glvertex3f -0.5,0.5,-0.5
            glvertex3f -0.5,-0.5,-0.5
         glend
         glbegin %gl_quads
            glcolor3f 0.5,1,0.5
            glvertex3f -0.5,-0.5,0.5  'top face
            glvertex3f -0.5,-0.5,-0.5
            glvertex3f 0.5,-0.5,-0.5
            glvertex3f 0.5,-0.5,0.5
         glend
         glbegin %gl_quads
            glcolor3f 1,0.5,0.5
            glvertex3f -0.5,0.5,0.5  'bottom face
            glvertex3f 0.5,0.5,0.5
            glvertex3f 0.5,0.5,-0.5
            glvertex3f -0.5,0.5,-0.5
         glend
         glpopmatrix
    END SUB
    '
    ' * Get keyboard input
    '
    SUB GetKeyBoard
    
        LOCAL Key AS WORD
    
        Key=getAsyncKeystate(%vk_left)         'Rotate left.
        IF Key>255 THEN
            CALL GetHorzVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xup,Yup,Zup)
            CALL GetupVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xhorz,Yhorz,Zhorz)
            CALL rotateview(0.01,Xup,Yup,Zup)
        END IF
        Key=getAsyncKeystate(%vk_right)        'Rotate right.
        IF Key>255 THEN
            CALL GetHorzVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xup,Yup,Zup)
            CALL GetupVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xhorz,Yhorz,Zhorz)
            CALL rotateview(-0.01,Xup,Yup,Zup)
        END IF
         Key=getAsyncKeystate(%vk_down)        'Pitch up.
        IF Key>255 THEN
            CALL GetHorzVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xup,Yup,Zup)
            CALL GetupVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xhorz,Yhorz,Zhorz)
            CALL rotateview(0.01,Xhorz,Yhorz,Zhorz)
        END IF
        Key=getAsyncKeystate(%vk_up)           'Pitch down.
        IF Key>255 THEN
            CALL GetHorzVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xup,Yup,Zup)
            CALL GetupVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xhorz,Yhorz,Zhorz)
            CALL rotateview(-0.01,Xhorz,Yhorz,Zhorz)
        END IF
        Key=getAsyncKeystate(%vk_Z)            'Move ahead
        IF Key>255 THEN
            CALL MoveCamera(1)
        END IF
        Key=getAsyncKeystate(%vk_X)            'Move back
        IF Key>255 THEN
            CALL MoveCamera(-1)
        END IF
        Key=getAsyncKeystate(%vk_A)            'Roll left.
        IF Key>255 THEN
            CALL GetHorzVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xup,Yup,Zup)
            CALL spinview(0.01,xview-xposition,yview-yposition,zview-zposition)
        END IF
        Key=getAsyncKeystate(%vk_S)            'Roll right.
        IF Key>255 THEN
            CALL GetHorzVec(Xview-Xposition,Yview-Yposition,Zview-Zposition,_
                         Xup,Yup,Zup)
            CALL spinview(-0.01,xview-xposition,yview-yposition,zview-zposition)
        END IF
    END SUB
    '
    ' Move camera towards or back from your view vector.
    '
    SUB MoveCamera(BYVAL speed AS SINGLE)
    
        XvVector=Xview-Xposition
        YvVector=Yview-Yposition
        ZvVector=Zview-Zposition
    
        Xposition=Xposition+(XvVector*speed)
        Yposition=Yposition+(YvVector*speed)
        Zposition=Zposition+(ZvVector*speed)
    
        Xview=Xview+(XvVector*speed)
        Yview=Yview+(YvVector*speed)
        Zview=Zview+(ZvVector*speed)
    
    END SUB
    '
    ' Rotate Camera (Get New Position of View Vector)
    '
    SUB RotateView(BYVAL angle AS SINGLE,BYVAL Xaxis AS SINGLE,BYVAL Yaxis AS SINGLE,BYVAL Zaxis AS SINGLE)
    
        LOCAL Xnew AS SINGLE
        LOCAL Ynew AS SINGLE
        LOCAL Znew AS SINGLE
        LOCAL CosAngle AS SINGLE
        LOCAL SinAngle AS SINGLE
    
        XvVector=Xview-Xposition
        YvVector=Yview-Yposition
        ZvVector=Zview-Zposition
    
        CosAngle=COS(angle)
        SinAngle=SIN(angle)
    
        Xnew=(CosAngle+(1-CosAngle)*xaxis*xaxis)*XvVector
        Xnew=Xnew+((1-CosAngle)*xaxis*yaxis-zaxis*SinAngle)*YvVector
        Xnew=Xnew+((1-CosAngle)*xaxis*zaxis+yaxis*SinAngle)*ZvVector
    
        Ynew=((1-CosAngle)*xaxis*yaxis+zaxis*SinAngle)*XvVector
        Ynew=Ynew+(CosAngle+(1-CosAngle)*yaxis*yaxis)*YvVector
        Ynew=Ynew+((1-CosAngle)*yaxis*zaxis-xaxis*SinAngle)*ZvVector
    
        Znew=((1-CosAngle)*xaxis*zaxis-yaxis*SinAngle)*XvVector
        Znew=Znew+((1-CosAngle)*yaxis*zaxis+xaxis*SinAngle)*YvVector
        Znew=Znew+(CosAngle+(1-CosAngle)*Zaxis*Zaxis)*ZvVector
    
        Xview=Xposition+Xnew
        Yview=Yposition+Ynew
        Zview=Zposition+Znew
    
    END SUB
    '
    ' Get Perpendicular vector from View Vector and Up Vector
    '
    SUB GetHorzVec(BYVAL Xvec AS SINGLE,BYVAL Yvec AS SINGLE,BYVAL Zvec AS SINGLE,_
                BYVAL Xvec2 AS SINGLE,BYVAL Yvec2 AS SINGLE,BYVAL Zvec2 AS SINGLE)
    
        'Find vector perpendicular to two given vectors.
    
        Xhorz=((Yvec*Zvec2)-(Zvec*Yvec2))
        Yhorz=((Zvec*Xvec2)-(Xvec*Zvec2))
        Zhorz=((Xvec*Yvec2)-(Yvec*Xvec2))
    
        'Calculate magnitude of vector (length)
    
        Magnitude=SQR(Xhorz*Xhorz+Yhorz*Yhorz+Zhorz*Zhorz)
    
        'Calculate Normal of vector (set length to 1)
    
        Xhorz=Xhorz/Magnitude
        Yhorz=Yhorz/Magnitude
        Zhorz=Zhorz/Magnitude
    END SUB
    '
    ' Get Perpendicular vector from view & horizontal vectors
    '
    SUB GetUpVec(BYVAL Xvec AS SINGLE,BYVAL Yvec AS SINGLE,BYVAL Zvec AS SINGLE,_
                BYVAL Xvec2 AS SINGLE,BYVAL Yvec2 AS SINGLE,BYVAL Zvec2 AS SINGLE)
    
        'Find vector perpendicular to two given vectors.
    
        Xup=(Yvec*Zvec2)-(Zvec*Yvec2)
        Yup=(Zvec*Xvec2)-(Xvec*Zvec2)
        Zup=(Xvec*Yvec2)-(Yvec*Xvec2)
    
        'Calculate magnitude of vector (length)
    
        Magnitude=SQR(Xup*Xup+Yup*Yup+Zup*Zup)
    
        'Calculate Normal of vector (set length to 1)
    
        Xup=-Xup/Magnitude
        Yup=-Yup/Magnitude
        Zup=-Zup/Magnitude
    END SUB
    '
    ' Spin Camera (Get New Position of Up Vector.  Up vector spins around view vector.)
    '
    SUB SpinView(BYVAL angle AS SINGLE,BYVAL Xaxis AS SINGLE,BYVAL Yaxis AS SINGLE,BYVAL Zaxis AS SINGLE)
    
        LOCAL Xnew AS SINGLE
        LOCAL Ynew AS SINGLE
        LOCAL Znew AS SINGLE
        LOCAL CosAngle AS SINGLE
        LOCAL SinAngle AS SINGLE
    
        CosAngle=COS(angle)
        SinAngle=SIN(angle)
    
        Xnew=(CosAngle+(1-CosAngle)*xaxis*xaxis)*Xup
        Xnew=Xnew+((1-CosAngle)*xaxis*yaxis-zaxis*SinAngle)*Yup
        Xnew=Xnew+((1-CosAngle)*xaxis*zaxis+yaxis*SinAngle)*Zup
    
        Ynew=((1-CosAngle)*xaxis*yaxis+zaxis*SinAngle)*Xup
        Ynew=Ynew+(CosAngle+(1-CosAngle)*yaxis*yaxis)*Yup
        Ynew=Ynew+((1-CosAngle)*yaxis*zaxis-xaxis*SinAngle)*Zup
    
        Znew=((1-CosAngle)*xaxis*zaxis-yaxis*SinAngle)*Xup
        Znew=Znew+((1-CosAngle)*yaxis*zaxis+xaxis*SinAngle)*Yup
        Znew=Znew+(CosAngle+(1-CosAngle)*Zaxis*Zaxis)*Zup
    
        Xup=Xnew
        Yup=Ynew
        Zup=Znew
    END SUB
    ------------------
Working...
X