; ------------------------------------------------------
; gluLookAt camera
; Copyright (c) 2005-2016, Franck Charlet
; All rights reserved.
; ------------------------------------------------------
; buildblock RELEASE
;       CAPT %5\Release.bat
; buildblockend
; buildblock DEBUG
;       CAPT %5\Debug.bat
; buildblockend

; ------------------------------------------------------
; Constants
SCREEN_WIDTH            equ     800
SCREEN_HEIGHT           equ     600
SCREEN_BPP              equ     32

; ------------------------------------------------------
; Includes
                        include ..\Common_Src\FrameWork.asm
                        include ..\Common_Src\Camera.asm
                        include ..\Common_Src\Fonts.asm
                        include ..\Common_Src\Picture.asm
                        include ..\Common_Src\Textures.asm

; ------------------------------------------------------
; Variables
lFont                   dd      0

Camera_Position         VERTEX  <0.0, 0.0, 0.0>
Camera_Angles           VERTEX  <0.0, 0.0, 0.0>

lst_Sphere              dd      0
Quadric_Sphere          dd      0

Move_Speed              dd      25.0
Rotate_Speed            dd      30.0

Texture1                PICTURE <>
Texture1_Id             dd      0

Rotate_Planet_Angle     dd      0
Rotate_Planet_Speed     dd      2.0

; ------------------------------------------------------
; Name: Initialize()
; Desc: Perform the various initializations
Initialize              proc

                        invoke  glClearDepth, CDBL(1.0)
                        invoke  glHint, GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST
                        invoke  glClearColor, 0, 0, 0, CFLT(1.0)
                        invoke  glEnable, GL_NORMALIZE
                        invoke  glEnable, GL_CULL_FACE
                        invoke  glEnable, GL_DEPTH_TEST

                        invoke  glShadeModel, GL_FLAT

                        ; Could be a .BMP .GIF .JPG .EMF .WMF .ICO .CUR etc. as well.
                        invoke  Load_PICTURE, CSTR("..\..\Media\earth.gif"), addr Texture1, -1
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("Can't load texture file")
                                mov     eax, FALSE
                                ret
                        .endif
                        
                        invoke  Init_Textures_Context

                        invoke  Create_2D_Texture, Texture1.Datas, Texture1._Width, TRUE, GL_RGBA, GL_RGBA
                        mov     Texture1_Id, eax
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("Can't create texture")
                                mov     eax, FALSE
                                ret
                        .endif

                        ; Create the fonts
                        invoke  Create_Font_Bitmap, CSTR("Courier New"), 12, FW_NORMAL
                        mov     lFont, eax
                        .if     eax == 0
                                invoke  Set_Error_Msg, CSTR("Can't create font")
                                xor     eax, eax
                                ret
                        .endif

                        ; Create a sphere
                        invoke  glGenLists, 1
                        mov     lst_Sphere, eax

                        invoke  glNewList, eax, GL_COMPILE
                                invoke  gluNewQuadric
                                mov     Quadric_Sphere, eax
                                invoke  gluQuadricOrientation, Quadric_Sphere, GLU_OUTSIDE
                                invoke  gluQuadricDrawStyle, Quadric_Sphere, GLU_FILL
                                invoke  gluQuadricTexture, Quadric_Sphere, GL_TRUE
                                invoke  gluSphere, Quadric_Sphere, CDBL(200.0), 64, 64
                        invoke  glEndList

                        mov     eax, TRUE
                        ret
Initialize              endp

; ------------------------------------------------------
; Name: Deinitialize()
; Desc: Free allocated resources
Deinitialize            proc
                        invoke  gluDeleteQuadric, Quadric_Sphere
                        invoke  glDeleteLists, lst_Sphere, 1
                        invoke  Destroy_Font, lFont
                        invoke  Unload_PICTURE, addr Texture1
                        ret
Deinitialize            endp

; ------------------------------------------------------
; Name: Update()
; Desc: Update the scene
Update                  proc    FrameRate:real4
                        local   Tmp_Speed:real4

                        mov     Tmp_Speed, 0
                        mov     Camera_Position.x, 0
                        mov     Camera_Position.y, 0
                        mov     Camera_Position.z, 0
                        mov     Camera_Angles.x, 0
                        mov     Camera_Angles.y, 0
                        mov     Camera_Angles.z, 0

                        ; Update scene here
                        fld     Rotate_Planet_Angle
                        fld     Rotate_Planet_Speed
                        fmul    FrameRate
                        faddp   st(1), st(0)
                        fstp    Rotate_Planet_Angle

                        invoke  DInput_Get_Key, DIK_LEFT
                        test    eax, eax
                        jz      Increase_X_Angle
                        fld     dword ptr [Rotate_Speed]
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Angles.x]
                        fstp    dword ptr [Camera_Angles.x]
Increase_X_Angle:
                        invoke  DInput_Get_Key, DIK_RIGHT
                        test    eax, eax
                        jz      Decrease_X_Angle
                        fld     dword ptr [Rotate_Speed]
                        fchs
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Angles.x]
                        fstp    dword ptr [Camera_Angles.x]
Decrease_X_Angle:
                        invoke  DInput_Get_Key, DIK_UP
                        test    eax, eax
                        jz      Increase_Y_Angle
                        fld     dword ptr [Rotate_Speed]
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Angles.y]
                        fstp    dword ptr [Camera_Angles.y]
Increase_Y_Angle:
                        invoke  DInput_Get_Key, DIK_DOWN
                        test    eax, eax
                        jz      Decrease_Y_Angle
                        fld     dword ptr [Rotate_Speed]
                        fchs
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Angles.y]
                        fstp    dword ptr [Camera_Angles.y]
Decrease_Y_Angle:
                        invoke  DInput_Get_Key, DIK_PGUP
                        test    eax, eax
                        jz      Increase_Z_Angle
                        fld     dword ptr [Rotate_Speed]
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Angles.z]
                        fstp    dword ptr [Camera_Angles.z]
Increase_Z_Angle:
                        invoke  DInput_Get_Key, DIK_PGDN
                        test    eax, eax
                        jz      Decrease_Z_Angle
                        fld     dword ptr [Rotate_Speed]
                        fchs
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Angles.z]
                        fstp    dword ptr [Camera_Angles.z]
Decrease_Z_Angle:
                        invoke  DInput_Get_Key, DIK_NUMPAD2
                        test    eax, eax
                        jz      Move_Backward
                        fld     dword ptr [Move_Speed]
                        fchs
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Position.z]
                        fstp    dword ptr [Camera_Position.z]
Move_Backward:
                        invoke  DInput_Get_Key, DIK_NUMPAD8
                        test    eax, eax
                        jz      Move_Forward
                        fld     dword ptr [Move_Speed]
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Position.z]
                        fstp    dword ptr [Camera_Position.z]
Move_Forward:
                        invoke  DInput_Get_Key, DIK_NUMPAD4
                        test    eax, eax
                        jz      Move_Left
                        fld     dword ptr [Move_Speed]
                        fchs
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Position.x]
                        fstp    dword ptr [Camera_Position.x]
Move_Left:
                        invoke  DInput_Get_Key, DIK_NUMPAD6
                        test    eax, eax
                        jz      Move_Right
                        fld     dword ptr [Move_Speed]
                        fmul    dword ptr [FrameRate]
                        fadd    dword ptr [Camera_Position.x]
                        fstp    dword ptr [Camera_Position.x]
Move_Right:
                        invoke  Camera_Move, addr Camera_Position
                        invoke  Camera_Rotate, addr Camera_Angles

                        invoke  DInput_Get_Key, DIK_ESCAPE
                        test    eax, eax
                        jz      Esc_Pressed
                        invoke  Terminate_Application
Esc_Pressed:            ret
Update                  endp

; ------------------------------------------------------
; Name: Draw()
; Desc: Draw the scene
Draw                    proc
                        
                        invoke  glClear, GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT

                        invoke  glPushMatrix
                                invoke  Camera_LookAt

                                invoke  glColor3f, CFLT(1.0), CFLT(1.0), CFLT(1.0)
                                invoke  glTranslatef, CFLT(500.0), CFLT(0.0), CFLT(0.0)
                                invoke  glRotatef, CFLT(180.0), CFLT(0.0), CFLT(1.0), CFLT(0.0)
                                invoke  glRotatef, Rotate_Planet_Angle, CFLT(0.0), CFLT(0.0), CFLT(1.0)
                                invoke  glEnable, GL_TEXTURE_2D
                                invoke  glBindTexture, GL_TEXTURE_2D, Texture1_Id
                                ; Smooth it when far from the observer
                                invoke  glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR
                                invoke  glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR

                                invoke  glCallList, lst_Sphere

                                invoke  glDisable, GL_TEXTURE_2D
                        invoke  glPopMatrix

                        invoke  Enter_2D_Mode, INT2FLT(SCREEN_WIDTH), INT2FLT(SCREEN_HEIGHT)
                                invoke  glTranslatef, CFLT(0.0), CFLT(0.0), CFLT(-1.0)
                                invoke  glColor3f, CFLT(0.4), CFLT(0.8), CFLT(0.3)
                                invoke  Display_2D_Text, INT2FLT(10), INT2FLT(512), lFont, CSTR("KEYPAD 8/2: Move camera forward/backward"), 40
                                invoke  Display_2D_Text, INT2FLT(10), INT2FLT(522), lFont, CSTR("KEYPAD 4/6: Move camera left/right"), 34
                                invoke  Display_2D_Text, INT2FLT(10), INT2FLT(532), lFont, CSTR("ARROWS: Rotate camera around X/Y axes"), 37
                                invoke  Display_2D_Text, INT2FLT(10), INT2FLT(542), lFont, CSTR("PAGE UP/DOWN: Rotate camera around Z axis"), 41
                        invoke  Leave_2d_Mode
                        ret
Draw                    endp

end start
