'Beispiel für OpenGl mit Glut unter Linux
'Ich danke Eastler der mit seinem Tutorial und dem Grundstock für meinen Beitrag legte.
'
' ueberarbeitet und ergaenzt von TJF

'-------------------------
'Includes
'-------------------------
#INCLUDE ONCE "fbgfx.bi"
#INCLUDE ONCE "GL/gl.bi"
#INCLUDE ONCE "GL/glu.bi"
#INCLUDE ONCE "vbcompat.bi" '<-um Zahlen per "format()" formatieren zu können
#INCLUDE ONCE "GL/glut.bi"  ' use glut only for Linux-version

#LIBPATH "../fbsound0.10/lib"
#INCLUDE ONCE "../fbsound0.10/inc/fbsound.bi"
fbs_Set_PlugPath("../fbsound0.10/lib/")

#DEFINE NL CHR(13, 10)
#DEFINE Zeile(_D_,_E_) _D_ & STRING(79 - LEN(_E_) - LEN(_D_), " ") & _E_
#DEFINE InfoText _
  Zeile("Ostereier 3D", "Easter eggs 3D") & NL & _
  NL & _
  Zeile("Lizenz: GPLv3", "License: GPLv3") & NL & _
  "                                   (C) 2011 by:" & NL & _
  Zeile("hans-joerg{dot}doering[at]nexgo{dot}de   &", "Thomas[dot]Freiherr{at}gmx[dot]net") & NL & _
  NL & _
  NL & _
  Zeile("TASTATURSTEUERUNG", "KEYBOARD CONTROL") & NL & _
  NL & _
  Zeile("Pfeiltasten = Ansicht drehen", "arrows = turn view") & NL & _
  Zeile("Leertaste = vorwaerts", "space = forward") & NL & _
  Zeile("r = zurueck", "r = backward") & NL & _
  Zeile("ESC = beenden", "ESC = quit") & NL & _
  NL & _
  Zeile("MAUSSTEUERUNG", "MOUSECONTROL") & NL & _
  NL & _
  Zeile("Maus am Fensterrand bewirkt", "mouse at border") & NL & _
  Zeile("Drehung in diese Richtung.", "turns view in that direction") & NL & _
  Zeile("linke Maustaste = vorwaerts", "left mouse button = forward") & NL & _
  Zeile("rechte Maustaste = rueckwaerts", "right mouse button = backward") & NL & _
  NL & _
  NL & _
  Zeile("VIEL SPASS!", "HAVE FUN!") & NL & _
  NL & _
  "                           Init ... ";

#DEFINE SCHLUSS(_T_) ?_T_ : ? Zeile("Taste druecken","Press a key!") : _
                     BEEP : SLEEP : END 1

CONST _
  DATA_PFAD = "data", _
  Pi_ = 3.14159265358979323846, _
  PIU = Pi_ / 180, _
  Pi2_ = Pi_ / 2, _
  MT = 10, _
  MB = 10, _
  Obj_max = 600, _
  Eier = 30 ' max 44

'======== Position für Kamera und Drehwinkel ==========================00
DIM SHARED AS SINGLE _
  Startzeit, _
  DrehX, DrehY, VCam, _
  CamX = .0, CamY = -1.65, CamZ = -3., _
  WiXCam = 10, WiYCam = 0, WiZCam = 0, _
        AmbientLight(0 TO 3) = {-0.15, -0.15, -0.15, 0.0}, _
        DiffuseLight(0 TO 3) = { 1.0 ,  1.0 ,  1.0 , 1.0}, _
          ColorLight(0 TO 3) = { 1.0 ,  1.0 ,  1.0 , 0.0}, _
       LightPosition(0 TO 3) = { 1.0 ,  0.0 ,  1.0 , 1.0}

DIM SHARED AS INTEGER _
  MausX, MausY, MausButtons = 0, MausImFenster, _
  Resteier, Lauf, _
  WavFind, SouHint, SouEnd

DIM SHARED AS UINTEGER _
  TexNarzisse, TexEi, TexGras, TexTux, TexKrousB, _
  TexTulpeG, TexTulpeR, TexNadeln, TexMauer, TexHase, TexOstern, _
  ScreenW = 1024, _
  ScreenH =  600

TYPE Object
  AS SINGLE x, y, z
  AS SINGLE rot = 1.0, gruen = 1.0, blau = 1.0
  AS SINGLE Radius
  AS SINGLE wi(2)
  AS UINTEGER TexturName
  AS INTEGER gezeichnet
END TYPE
DIM SHARED AS Object oj(0 TO Obj_max)


FUNCTION TexturLaden(BYREF dateiname AS STRING) AS UINTEGER
  STATIC AS UBYTE count = ASC("A") : ? CHR(count); : count += 1
  DIM AS INTEGER breit, hoch, offset, biSize
  VAR ff = FREEFILE
  IF OPEN(dateiname FOR BINARY AS #ff) THEN RETURN 0
    GET #ff, 3,  biSize
    GET #ff, 11, offset
    GET #ff, 19, breit 'Breite aus der BMP-Datei holen
    GET #ff, 23, hoch  'Höhe aus der BMP-Datei holen
    DIM AS UBYTE Punkt(biSize - offset)
    VAR Pza = 0
    FOR i AS INTEGER = biSize - 1 TO offset STEP -1
      GET #ff, i, Punkt(Pza)
      Pza += 1
    NEXT
  CLOSE #ff
  DIM AS UINTEGER TexturNummer
  glGenTextures 1, @TexturNummer
  glBindTexture GL_TEXTURE_2D, TexturNummer
  glTexImage2D GL_TEXTURE_2D, 0, GL_RGBA, breit, hoch, 0, GL_RGBA, GL_UNSIGNED_BYTE, @Punkt(0)   ' @SpBmpPixelZeiger
  glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
  glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
  RETURN TexturNummer
END FUNCTION

FUNCTION WavLaden(BYREF dateiname AS STRING) AS INTEGER
  STATIC AS UBYTE count = ASC("1") : ? CHR(count); : count += 1
  VAR Wav = 0 : IF fbs_Load_MP3File(dateiname, @Wav) THEN RETURN Wav
  SCHLUSS("error: fbs_Load_MP3File() !")
END FUNCTION

FUNCTION SouLaden(BYREF dateiname AS STRING) AS INTEGER
  VAR Sou = 0 : IF fbs_Create_Sound(WavLaden(dateiname), @Sou) THEN RETURN Sou
  SCHLUSS("error: fbs_Create_Sound() !")
END FUNCTION

SUB def_oj()
  DrehX = 40.0 : DrehY = 60.0 : VCam = 0.2
  MausX = ScreenW SHR 1 : MausY = ScreenH SHR 1

' ===================Daten für Objekte ============================
  '==== Objekt Eier ====
  VAR Nr = 0
  Resteier = Eier
  FOR Nr = 0 TO Eier
    oj(Nr).Radius = 0.5
    oj(Nr).x = (RND * 120) - 60
    oj(Nr).y = oj(Nr).Radius/1.2
    oj(Nr).z = (RND * 120) - 60
    oj(Nr).gruen = 1.0 * RND
    oj(Nr).blau = 1.0 * RND
    SELECT CASE AS CONST CUINT(RND * 4)
    CASE 1    : oj(Nr).TexturName = TexNarzisse
    CASE 2    : oj(Nr).TexturName = TexHase
    CASE 3    : oj(Nr).TexturName = TexEi
    CASE ELSE : oj(Nr).TexturName = TexTux : oj(Nr).wi(1) = (RND * 45) - 45
    END SELECT
  NEXT

  '==== Objekt Hase ====
  Nr = 45
  oj(Nr).Radius = 1.5
  oj(Nr).x = 1
  oj(Nr).y = oj(Nr).Radius/1.8
  oj(Nr).z = -2.3
  oj(Nr).wi(0) = -90
  oj(Nr).wi(1) = -45
  oj(Nr).wi(2) = 0
  oj(Nr).TexturName = TexHase

  '==== Objekt Tux ====
  Nr = 46
  oj(Nr).Radius = 0.5
  oj(Nr).x = 0
  oj(Nr).y = oj(Nr).Radius/1.8
  oj(Nr).z = -2
  oj(Nr).wi(0) = -90
  oj(Nr).wi(1) = -45
  oj(Nr).wi(2) = 0
  oj(Nr).TexturName = TexTux

  '==== Objekt KrousB ====
  Nr = 47
  oj(Nr).Radius = 0.5
  oj(Nr).x = 1
  oj(Nr).y = oj(Nr).Radius/1.8
  oj(Nr).z = -3
  oj(Nr).wi(0) = -90
  oj(Nr).wi(1) = -45
  oj(Nr).wi(2) = 0
  oj(Nr).TexturName = TexKrousB

  '==== Objekt Ostergruss ====
  Nr = 48
  oj(Nr).Radius = 1.0
  oj(Nr).x = -1
  oj(Nr).y = 1
  oj(Nr).z = -4
  oj(Nr).wi(0) = -90
  oj(Nr).wi(1) = -45
  oj(Nr).wi(2) = 0
  oj(Nr).TexturName = TexOstern

  '==== Objekt Nummer 6  Ei des Kolumbus ====
  Nr = 49
  oj(Nr).Radius = 0.55
  oj(Nr).x = (RND * 120) - 60
  oj(Nr).y = oj(Nr).Radius/1.2
  oj(Nr).z = (RND * 120) - 60
  oj(Nr).gruen = 1.0 * RND
  oj(Nr).blau = 1.0 * RND
  oj(Nr).TexturName = TexNarzisse

  '==== Objekt Blumen ====
  FOR Nr = 50 TO 100
    oj(Nr).TexturName = TexKrousB
    oj(Nr).Radius = 0.5
    oj(Nr).x = (RND * 120) - 60
    oj(Nr).y = oj(Nr).Radius/1.8
    oj(Nr).z = (RND * 120) - 60
  NEXT

  '==== Objekt Blumen ====
  FOR Nr = 101 TO 200
    VAR Tulpe = CUINT(RND * 2)
    oj(Nr).Radius = 0.7 + RND * 0.5
    oj(Nr).x = (RND * 120) - 60
    oj(Nr).y = oj(Nr).Radius/1.8
    oj(Nr).z = (RND * 120) - 60
    IF Tulpe THEN
      oj(Nr).TexturName = TexTulpeR
    ELSE
      oj(Nr).wi(1) = -45 + (RND * 45)
      oj(Nr).TexturName = TexTulpeG
    END IF
  NEXT

  '==== Objekt Haus  ====
  FOR Nr = 201 TO 219
    VAR Tulpe = CUINT(RND * 2)
    oj(Nr).Radius = 2.6 + RND * .5
    oj(Nr).x = (RND * 120) - 60
    oj(Nr).y = .3
    oj(Nr).z = (RND * 120) - 60
    oj(Nr).TexturName = TexMauer
  NEXT

  '==== Objekt Busch ====
  FOR Nr = 220 TO 250
    oj(Nr).Radius = 5.5
    oj(Nr).x = (RND * 120) - 60
    oj(Nr).y = oj(Nr).Radius / 1.8
    oj(Nr).z = (RND * 120) - 60
    oj(Nr).TexturName = TexNadeln
  NEXT

  '==== Boden ====
  Nr = 400
  VAR si = 10
  FOR MTZa AS INTEGER = 1 TO MT
    FOR MBZa AS INTEGER = 1 TO MB
      oj(Nr).Radius = si / SQR(2)
      oj(Nr).x = MBZa * si * 1.4 - 75
      oj(Nr).y = 0
      oj(Nr).z = MTZa * si * 1.4 - 75
      Nr += 1
    NEXT
  NEXT
END SUB

#DEFINE MAX(_A_, _B_) IIF(_A_ > _B_, _A_, _B_)
#DEFINE MIN(_A_, _B_) IIF(_A_ < _B_, _A_, _B_)
#DEFINE CheckPos(_V_) _V_ = MAX(MIN(_V_, 65.), -65.)
#DEFINE CheckPoWi(_W_) WHILE _W_ >  180. : _W_ -= 360. : WEND
#DEFINE CheckNeWi(_W_) WHILE _W_ < -180. : _W_ += 360. : WEND
#MACRO Turn1(xn, yn, zn, x, y, z, w)
  si = SIN(w * PIU)
  co = COS(w * PIU)
  xn = x * co + z * si
  yn = y
  zn = x * si - z * co
#ENDMACRO

#MACRO TurnVertex(_X_, _Y_, _Z_)
  Turn1(rx, ry, rz, _X_, _Y_, _Z_, oj(obj).wi(1)) ' Drehung um Y-Achse
  Turn1(ey, ex, ez,  ry,  rx,  rz, oj(obj).wi(0)) ' Drehung um X-Achse
  Turn1(rx, rz, ry,  ex,  ez,  ey, oj(obj).wi(2)) ' Drehung um Z-Achse
  rx += oj(obj).x
  ry += oj(obj).y
  rz += oj(obj).z
  glVertex3f rx, ry, rz
#ENDMACRO

SUB Ei(BYVAL obj AS INTEGER, BYVAL z AS SINGLE, BYVAL s AS SINGLE, _
       BYVAL BZa AS INTEGER, BYVAL LZa AS INTEGER)
  glEnable GL_TEXTURE_2D
  glBegin GL_TRIANGLE_STRIP  '<<<<nur hier was zu ändern ;-)
  glColor3f oj(obj).rot, oj(obj).gruen, oj(obj).blau     ' Zeichenfarbe auf weiß

  DIM AS SINGLE ex, ey, ez, si, co, rx, ry, rz
  VAR BrWi = 2 * Pi_ / BZa, BrWiy = Pi_ / LZa, d = 1.0, e = z + 1
  FOR L AS INTEGER = 0 TO LZa - 1
    d -= s
    FOR B AS INTEGER = 0 TO BZa
      glTexCoord2d B / BZa, 1 - (L / LZa)
      VAR wix = B * BrWi
      VAR wi = L * BrWiy
      VAR swi = oj(obj).Radius * SIN(wi) * d
      VAR cwi = oj(obj).Radius * COS(wi) * e
      TurnVertex(swi * SIN(wix), cwi, swi * COS(wix))

      glTexCoord2d B / BZa, 1 - ((L + 1) / LZa)
      wi = (L + 1) * BrWiy
      swi = oj(obj).Radius * SIN(wi) * (d - s)
      cwi = oj(obj).Radius * COS(wi) * e
      TurnVertex(swi * SIN(wix), cwi, swi * COS(wix))
    NEXT
  NEXT
  glEND
  glDisable GL_TEXTURE_2D
END SUB

SUB Flaeche(BYVAL obj AS INTEGER)
  glEnable GL_TEXTURE_2D
  glColor4f(1.0f, 1.0f, 1.0f, 1.0f) ' Volle Helligkeit, 50% Alpha ( NEU )
  glBegin GL_QUADS 'Begin GL_TRIANGLE_FAN
  VAR w = oj(obj).Radius
  glTexCoord2i 0, 1 : glVertex3f oj(obj).x - w, .0, oj(obj).z - w
  glTexCoord2i 0, 0 : glVertex3f oj(obj).x - w, .0, oj(obj).z + w
  glTexCoord2i 1, 0 : glVertex3f oj(obj).x + w, .0, oj(obj).z + w
  glTexCoord2i 1, 1 : glVertex3f oj(obj).x + w, .0, oj(obj).z - w
  glEND
  glDisable GL_TEXTURE_2D
END SUB

SUB Blume(BYVAL obj AS INTEGER, BYVAL Tranz AS INTEGER = 1)
  glEnable GL_TEXTURE_2D
  glColor4f(1.0f, 1.0f, 1.0f, 1.0f) ' Volle Helligkeit, 50% Alpha ( NEU )
  IF Tranz THEN
    glEnable(GL_BLEND) ' Schalte Blending ein
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ' Blending Funktion für Durchsichtigkeit basiered auf dem Quell Alpha Wert ( NEU )
  END IF
  glBegin GL_QUADS 'Begin GL_TRIANGLE_FAN
  DIM AS SINGLE ex, ey, ez, si, co, rx, ry, rz
  VAR w = oj(obj).Radius / 2
  FOR i AS INTEGER = 0 TO 3
    SELECT CASE AS CONST i
    CASE 1    : glTexCoord2i 0, 1 : ex =  w : ey = 0 ' oben links
    CASE 2    : glTexCoord2i 0, 0 : ex =  w : ey = 2 * w ' unten links
    CASE 3    : glTexCoord2i 1, 0 : ex = -w : ey = 2 * w ' unten rechts
    CASE ELSE : glTexCoord2i 1, 1 : ex = -w : ey = 0 ' oben rechts
    END SELECT : rz = 0
    Turn1(rx, ry, rz, ex, ey, ez, WiYCam) ' Drehung um Y-Achse
    rx += oj(obj).x
    rz += oj(obj).z
    glVertex3f rx, ry, rz
  NEXT
  glEND
  glDisable GL_TEXTURE_2D
  glDisable(GL_BLEND)  ' Schalte Blending aus
END SUB

SUB display CDECL()
  glClear GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT
  glPushMatrix
  glLightfv(GL_LIGHT0, GL_POSITION, @LightPosition(0))
  glRotatef WiXCam, 1, 0, 0
  glRotatef WiYCam, 0, 1, 0
  glTranslatef CamX, CamY, CamZ

  glEnable GL_TEXTURE_2D  '***********Texturieren erlauben*************
  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) '/* nicht GL_DECAL oder GL_REPLACE */
  FOR i AS INTEGER = 400 TO 400 + MT * MB
    glBindTexture GL_TEXTURE_2D, TexGras
    Flaeche(i)
    glDisable GL_TEXTURE_2D
  NEXT
  FOR i AS INTEGER = 0 TO 250
    oj(i).gezeichnet = 0
  NEXT
  FOR Zeichenaktion AS INTEGER = 0 TO 250
    VAR obj = -1, CEntfMax = .0
    FOR Nr AS INTEGER = 0 TO 250
      IF oj(Nr).gezeichnet = 1 THEN CONTINUE FOR
      IF oj(Nr).Radius = 0 THEN CONTINUE FOR
      VAR x1 = oj(Nr).x + CamX
      VAR y1 = oj(Nr).y + CamY
      VAR z1 = oj(Nr).z + CamZ
      VAR CEntf = SQR(x1 * x1 + y1 * y1 + z1 * z1)
      IF oj(Nr).gezeichnet = 0 ANDALSO _
             oj(Nr).Radius > 0 ANDALSO _
                     CEntf > CEntfMax THEN obj = Nr : CEntfMax = CEntf
      IF CEntf < 8 THEN
        IF Nr <= Eier THEN
          oj(Nr).Radius = 0
          Resteier -= 1
          IF Resteier >= 0 THEN fbs_Play_Wave(WavFind, 1)
        END IF
      END IF
    NEXT : IF obj < 0 THEN EXIT FOR
    oj(obj).gezeichnet = 1
    glBindTexture GL_TEXTURE_2D, oj(obj).TexturName
    SELECT CASE AS CONST obj
    CASE   0 TO Eier : Ei(obj, 0.0, 0.03, 16, 16) : oj(obj).wi(1) += 1.2
    CASE  45         : Blume(obj)
    CASE  46         : Blume(obj)
    CASE  47         : Blume(obj)
    CASE  48         : Blume(obj)
    CASE  49         : Ei(obj, 0.0, 0.03, 16, 16) : oj(obj).wi(1) -= 1.7
    CASE  50 TO 100  : Blume(obj)
    CASE 101 TO 200  : Blume(obj)
    CASE 201 TO 219  : Ei(obj, 0.0, 0.0, 4, 3)
    CASE 220 TO 250  : Ei(obj, 2.0, 0.05, 16, 16)
    END SELECT
  NEXT
  glutSwapBuffers()
  glPopMatrix
END SUB

SUB Mouse CDECL(BYVAL button AS INTEGER, BYVAL state AS INTEGER, _
                BYVAL x AS INTEGER, BYVAL y AS INTEGER)
  Lauf XOR= 1
  MausButtons = button
END SUB

SUB MouseMotion CDECL(BYVAL x AS INTEGER , BYVAL y AS INTEGER)
  MausX = x
  MausY = y
END SUB

SUB MausAktion()
  IF Lauf THEN
    VAR wi = (WiYCam + 90) * PIU, f = VCam * COS(WiXCam * PIU)
    SELECT CASE AS CONST MausButtons
    CASE 0
      CamX += f * COS(wi)
      CamZ += f * SIN(wi)
    CASE 2
      CamX -= f * COS(wi)
      CamZ -= f * SIN(wi)
    END SELECT : CheckPos(CamX) : CheckPos(CamZ)
  END IF
  IF MausImFenster THEN
    VAR px = MausX / (ScreenW - 1)
    IF px < .5 THEN WiYCam -= DrehY * (.5 - px) ^ 4 : CheckNeWi(WiYCam)
    IF px > .5 THEN WiYCam += DrehY * (px - .5) ^ 4 : CheckPoWi(WiYCam)
    VAR py = MausY / (ScreenH - 1)
    IF py < .5 THEN IF WiXCam > -30 THEN WiXCam -= DrehX * (.5 - py) ^ 4
    IF py > .5 THEN IF WiXCam <  25 THEN WiXCam += DrehX * (py - .5) ^ 4
  END IF
END SUB

SUB timerFcn CDECL(BYVAL value AS INTEGER)
  STATIC AS INTEGER Zeit = 0, fa = 250
  STATIC AS SINGLE dx, dz, dwx, dwy
  MausAktion()
  IF Resteier >= 0 THEN
    glutSetWindowTitle STR(Eier - Resteier) + " gefundene Eier!    " + _
                       STR(Resteier + 1) + " Resteier"
  ELSE
    IF Zeit = 0 THEN
      DrehX = 0.0 : DrehY = 0.0 : VCam = 0.0
      dx = CamX / fa : dz = (CamZ + 3) / fa
      dwx = (WiXCam - 10) / fa : dwy = WiYCam / fa
      Zeit = CINT(TIMER - Startzeit)
      glutSetWindowTitle "Alle Eier gefunden (" + _
                          STR(Zeit) + _
                          " s)! Frohe Ostern wünschen Laiko & TJF."
      fbs_Set_SoundPaused(SouHint, TRUE)
      WHILE fbs_Get_PlayingSounds() = 0 : SLEEP 10 : WEND
      fbs_Play_Sound(SouEnd, 1)
    ELSE
      IF fa > 0 THEN fa -= 1 : CamX -= dx : WiXCam -= dwx : _
                               CamZ -= dz : WiYCam -= dwy
      IF fbs_Get_PlayingSounds() = 0 THEN
        SLEEP 1300
        DIM AS SHORT PTR pStart
        fbs_Get_SoundPointers(SouHint, @pStart)
        fbs_Set_SoundPointers(SouHint, , pStart)
        fbs_Set_SoundPaused(SouHint, FALSE)
        def_oj() : Startzeit = TIMER
        fa = 250 : Zeit = 0
        glutWarpPointer(MausX, MausY)
      END IF
    END IF
  END IF
  glutPostRedisplay()
  glutTimerFunc(25, @timerFcn, 0)
END SUB

SUB motionPassive CDECL(BYVAL X AS INTEGER , BYVAL Y AS INTEGER)
  MausX = X : MausY = Y
END SUB

SUB entry CDECL(BYVAL State AS INTEGER)
  MausImFenster = State
END SUB

SUB tasten CDECL(BYVAL key AS UBYTE, _
                 BYVAL xmouse AS INTEGER, BYVAL ymouse AS INTEGER)
  VAR f = VCam * COS(WiXCam * PIU), wy = (WiYCam + 90) * PIU
  SELECT CASE AS CONST key
  CASE 27 : END
  CASE 32 '*********** Vorwaerts ! ***********
    CamX += f * COS(wy)
    CamZ += f * SIN(wy)
  CASE 104 '******* Raeckwaerts ! ******************
    CamX -= f * COS(wy)
    CamZ -= f * SIN(wy)
  END SELECT : CheckPos(CamX) : CheckPos(CamZ)
END SUB

SUB processSpecialKeys CDECL(BYVAL key AS INTEGER, _
                             BYVAL x AS INTEGER, BYVAL y AS INTEGER)
  SELECT CASE AS CONST key
  CASE GLUT_KEY_UP    : IF WiXCam > -30 THEN WiXCam -= DrehX * .01
  CASE GLUT_KEY_DOWN  : IF WiXCam <  25 THEN WiXCam += DrehX * .01
  CASE GLUT_KEY_LEFT  : WiYCam -= DrehY * .01 : CheckNeWi(WiYCam)
  CASE GLUT_KEY_RIGHT : WiYCam += DrehY * .01 : CheckPoWi(WiYCam)
  END SELECT
END SUB

SUB WindowReshape CDECL(BYVAL W AS INTEGER, BYVAL H AS INTEGER)
  ScreenW = W : ScreenH = H
  glViewport (0, 0, w, h)
  glMatrixMode (GL_PROJECTION)
  glLoadIdentity ()
  STATIC AS CONST SINGLE d = 0.1, x = 0.1 / 5
  IF w > h THEN
    VAR a = w / h * x
    glFrustum (-a, a, -x, x, d, 200.0)
  ELSE
    VAR a = h / w * x
    glFrustum (-x, x, -a, a, d, 200.0)
  END IF
  glMatrixMode (GL_MODELVIEW)
END SUB


' ********* Main *********

SCREEN 12
? InfoText

'============ Sounds Laden aus mp3 ===========================
IF fbs_Init() = FALSE THEN _
          ? "Error: fbs_Init() !" : SCHLUSS(fbs_get_plugerror())
CHDIR DATA_PFAD
SouHint = SouLaden("Hintergrund.mp3")
WavFind = WavLaden("Eierfund.mp3")
 SouEnd = SouLaden("Finale.mp3")

'-------------------------
' Open-GL Init
glutInit(__FB_ARGC__, CAST(BYTE PTR, @__FB_ARGV__))

glutInitDisplayMode(GLUT_ALPHA OR GLUT_DOUBLE OR GLUT_DEPTH) 'GLUT_LUMINANCE.
glutInitWindowSize(ScreenW, ScreenH)
glutInitWindowPosition(100, 0)
glutCreateWindow("Osterei")

'Glut Callback Funktionen in denen die Mainloop Statfindet *********
glutDisplayFunc(@display)
glutMouseFunc(@Mouse)
glutMotionFunc(@MouseMotion)
glutTimerFunc(0, @timerFcn, 0)
glutPassiveMotionFunc(@motionPassive)
glutEntryFunc(@entry)
glutKeyboardFunc(@tasten)
glutSpecialFunc(@processSpecialKeys)
glutReshapeFunc(@WindowReshape)

'============ Texturen Laden aus BMP ===========================
TexNarzisse = TexturLaden("Narzise4.bmp")
      TexEi = TexturLaden("Buntei.bmp")
    TexGras = TexturLaden("Gras2.bmp")
     TexTux = TexturLaden("Tux.bmp")
  TexKrousB = TexturLaden("Kro_bl.bmp")
  TexTulpeG = TexturLaden("Tulpe.bmp")
  TexTulpeR = TexturLaden("Tulpe2.bmp")
  TexNadeln = TexturLaden("Nadeln.bmp")
   TexMauer = TexturLaden("Mauer.bmp")
    TexHase = TexturLaden("Hase.bmp")
  TexOstern = TexturLaden("Ostern.bmp")

def_oj()

glMatrixMode GL_MODELVIEW       ' Auf den Matrix-Modus Modelview schalten
glLoadIdentity                  ' und auch diesen auf Anfangswerte setzen
glClearColor 0.2, 0.6, 0.7, 1.0 ' Setze Farbe für löschen auf Mittelgrau

'init OpenGl*******************************+

glClearDepth 1.0          ' Depth-Buffer Löschen erlauben
glEnable GL_DEPTH_TEST    ' den Tiefentest GL_DEPTH_TEST einschalten
glClear GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT  'Tiefen- und Farbpufferbits löschen

glClearDepth(1.0)               '// Depth Buffer Setup
glEnable(GL_DEPTH_TEST)         '// Enables Depth Testing
glDepthFunc(GL_LEQUAL)          '// The Type Of Depth Test To Do
glCullFace(GL_BACK)             '// Set to Back
glFrontFace(GL_CCW)             '// Draw all surfaces CCW
glShadeModel(GL_SMOOTH)         '// Set shading model
glDisable(GL_LIGHTING)           '// Enable Lighting
'glEnable(GL_LIGHTING)           '// Enable Lighting
glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 360.0) 'Sputlicht 30 Grad
glLightfv(GL_LIGHT0,GL_AMBIENT, @AmbientLight(0))  '// Enable Ambient Light
glLightfv(GL_LIGHT0,GL_DIFFUSE, @ColorLight(0))    '// Enable Diffuse Light
glLightfv(GL_LIGHT0,GL_DIFFUSE, @DiffuseLight(0))  '// Enable Diffuse Light
glEnable(GL_LIGHT0)                                '// Enable Light0

glLightfv(GL_LIGHT0,GL_POSITION,@LightPosition(0)) '// Set our Light Position

glEnable(GL_COLOR_MATERIAL)                        '// Enable material colors
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)  '// Set to front for Ambient and Diffuse Light

? " ok!" & NL & NL & Zeile("Taste druecken!","Press a key!") & NL

SLEEP : IF ASC(INKEY()) = 27 THEN END
Startzeit = TIMER
fbs_Play_Sound(SouHint, -1)

glutWarpPointer(MausX, MausY)
glutMainLoop()
