'GL camera transform
'Relsoft 2004
'Rel.betterwebber.com

'Based on a very cool OpenGL series by
'DIGIBEN(Ben Humphrey) You da man!!!

'Also thanks to:
'Giuseppe D'Agata and Nehe for the Original Tute for GLFont
'Tobias Franke for the tute on dynamic terrain texture generation


'This uses Vertex Arrays for speed



DEFINT A - Z

const PI = 3.141593                     'PI for rotation
const SCR_WIDTH = 640                   'Width of the screen
const SCR_HEIGHT = 480                  'height of the screen
const BITSPP = 32                       '32 bits per pixel format

const TEXT_XMAX = 256
const TEXT_YMAX = 256

const MAXPOINTS = 64

const STEP_SIZE	 = 8		     					'Resolution of the mesh
const HEIGHT_RATIO = 0.28							'height ratio


const CAM_SPEED = .5



option explicit                         'Force declaration

'$include: "\sdl\sdl.bi"                'sdl function and constants declaration
'$include: "\gl\gl.bi"                  'OpenGL funks and consts
'$include: "\gl\glu.bi"                 'GL standard utility lib

Type Vector3d
    x       as single
    y       as single
    z       as single
End Type

Type CameraType
    m_Position  as vector3d
    m_Target    as vector3d
    m_Up        as vector3d
    m_Roll      as integer
End Type

Type Vertex3d
    x       as GLFloat
    y       as GLFloat
    z       as GLFloat
End type

Type TexCoord2d
    u       as GLFloat
    v       as GLFloat
end type

Type Model3d
    m_nIndices as integer
    m_nVertices as integer
    m_pVertex as GlFloat ptr
    m_pTexCoord as GlFloat ptr
    m_pIndex as GLuint ptr
end type



'Declarations
DECLARE SUB Init_GL_SDL(SDLscreen as SDL_Surface ptr)
Declare Sub SDL_GetEvents(EscapeVal as Integer)
Declare Sub draw_scene(vb as Model3d ptr)
Declare sub Init_Texture( hMap as SDL_Surface ptr, htexture() as ubyte)
Declare function Height(byval X as integer,byval Y as integer) as integer
Declare function RenderHeightMap() as Model3d ptr


declare sub vector_cross (v1 as vector3d, v2 as vector3d, vout as vector3d)
declare function vector_magnitude(v as vector3d) as single
declare sub vector_normalize (v as vector3d)
declare sub vector_add (v1 as vector3d, v2 as vector3d, vout as vector3d)
declare sub vector_sub (v1 as vector3d, v2 as vector3d, vout as vector3d)
declare sub camera_set_position(Byref Camera as CameraType, _
                                byval px as single, byval py as single, byval pz as single,_
                                byval vx as single, byval vy as single, byval vz as single,_
                                byval ux as single, byval uy as single, byval uz as single)
declare Sub camera_setview_by_mouse(Byref camera as CameraType)
declare Sub camera_rotate_view (Byref Camera as CameraType, byval angle as single,_
                                byval x as single, byval y as single, byval z as single)
declare Sub camera_move(Byref camera as CameraType, byval speed as single)
declare Sub camera_strafe(Byref Camera as CameraType, byval speed as single)



DECLARE sub Load_Images(Hmap as SDL_Surface Ptr, ImageFinal as SDL_Surface Ptr)


Declare sub Load_Font_Texture()
Declare sub BuildFont()
Declare sub KillFont()
Declare sub glPrint(byval x as GLint, byval  y as GLint, byref xstring  as string , byval xset as integer)


'*******************************************************************************************
'Main code
'*******************************************************************************************

	dim shared texture( (TEXT_XMAX * TEXT_YMAX) - 1 ) as unsigned byte
    dim shared scaleValue as single
    dim Shared Textid(0) as GLuint

    dim shared height_map as SDL_Surface ptr
	dim image_final as SDL_Surface ptr

    dim vb as Model3d ptr


	dim Shared Camera as CameraType
	dim shared roll_angle as integer

	Dim shared font_texture as GLuint '\
    dim shared floop   as GLuint      ' > glFont stuff
    dim shared fbase   as GLuint      '/

    dim Shared Path as string
    Dim shared FPS2 as single


	dim vpage as SDL_Surface ptr            'The screen we want to draw to
    dim Finished as integer                 'Quit or not?

    randomize timer

    path = "C:\compiler\freebasic\images\"
    path = ""
     
    Init_Texture  height_map, texture()
    Init_GL_SDL vpage                       'init GL SDL stuff

    vb = RenderHeightMap

    Load_Font_Texture
    BuildFont
    Load_Images height_map, image_final

    RenderHeightMap

    dim k as ubyte ptr
    Dim Frames as integer

    dim t as single
    dim stime as single


   	scaleValue = 0.2
   	roll_angle = 90
    camera_set_position Camera,0, 15, -15, 0, -20, 20, 0, 1, 0
    'camera_set_position Camera,0, 45, 0, 0, 0, 0, 0, 1, 0


    Finished = 0                            'set finished to false

	do
	    SDL_GetEvents(Finished)             'handle events

        camera.m_Roll = roll_angle


        Camera_setview_by_mouse camera


        k = SDL_GetKeyState(0)


	    if k[SDLK_ESCAPE] then
	       finished = -1
	    end if

  	    if k[SDLK_UP] then
            camera_move Camera, CAM_SPEED
	    end if
   	    if k[SDLK_DOWN] then
            camera_move Camera, -CAM_SPEED
	    end if

   	    if k[SDLK_RIGHT] then
            camera_strafe Camera, CAM_SPEED
	    end if
   	    if k[SDLK_LEFT] then
            camera_strafe Camera, -CAM_SPEED
	    end if

   	    if k[SDLK_W] then
            camera_move Camera, CAM_SPEED
	    end if
   	    if k[SDLK_S] then
            camera_move Camera, -CAM_SPEED
	    end if

	    if k[SDLK_A] then
            camera_strafe Camera, -CAM_SPEED
	    end if

  	    if k[SDLK_D] then
            camera_strafe Camera, CAM_SPEED
	    end if

   	    if SDL_GetMouseState(NULL, NULL) and SDL_BUTTON(SDL_BUTTON_LEFT) then
            roll_angle = roll_angle + 1
        End if
        if SDL_GetMouseState(NULL, NULL) and SDL_BUTTON(SDL_BUTTON_RIGHT) then
            roll_angle = roll_angle - 1
        End if


        frames = frames + 1
        t = (SDL_GetTicks() * 0.001) - stime
        if t > 2 then
            FPS2 = Frames/t
            SDL_WM_SetCaption "Frames per sec using Display lists:" + str$(FPS2), ""
            stime = (SDL_GetTicks() * 0.001)
            frames = 0
        end if
        draw_scene vb                       'Draw something
		SDL_GL_SwapBuffers                  'Flip to screen
		SDL_PumpEvents                      'force an event queue update(input, etc)
	loop until Finished


  	deallocate vb->m_pVertex
    deallocate vb->m_pTexcoord
	deallocate vb


    SDL_Quit

    End



'*******************************************************************************************
'SUBS/FUNKS
'*******************************************************************************************

'*******************************************************************************************
'Initializes GL+SDL
'Params: SDLscreen pointer to GL/SDL context to draw to
SUB Init_GL_SDL(SDLscreen as SDL_Surface ptr)

    dim Result as unsigned integer      'checker value for SDL initialization
	dim SDL_flags as integer            'Flags for SDL screen

    'OpenGL params for gluerspective
	dim FOVy as double            'Feild of view angle in Y
	dim Aspect as double          'Aspect of screen
	dim znear as double           'z-near clip distance
	dim zfar as double            'z-far clip distance


    'Let's set up our sdl flags variable

    SDL_flags = SDL_HWSURFACE                   'use Hardware surface
    SDL_flags = SDL_flags or SDL_DOUBLEBUF      'doublebuffer to prevent flicker
    SDL_flags = SDL_flags or SDL_OPENGL         'activate OpenGL
    SDL_flags = SDL_flags or SDL_FULLSCREEN     'FullScreen(REM for windowed)

    'Init everything for SDL(video,audio, key, joy, etc)
	result = SDL_Init(SDL_INIT_EVERYTHING)
	if result <> 0 then                     'error?
  		end 1                               'then quit
	end if

    'Set 640*480*32
    'SCR_WIDTH/HEIGHT/BITSPP are CONSTANTS declared at the main module
	SDLscreen = SDL_SetVideoMode(SCR_WIDTH, SCR_HEIGHT, BITSPP, SDL_flags)
	if SDLscreen = 0 then
		SDL_Quit
		end 1
	end if
	SDL_ShowCursor SDL_DISABLE

	SDL_WM_SetCaption "Sdl Template", ""       'Make caption if windowed

    'Set OpenGL ViewPort to screen dimensions
	glViewport 0, 0, SCR_WIDTH, SCR_HEIGHT

	'Set current Mode to projection(ie: 3d)
	glMatrixMode GL_PROJECTION

    'Load identity matrix to projection matrix
	glLoadIdentity

    'Set gluPerspective params
    FOVy = 80/2                                     '45 deg fovy
    Aspect = SCR_WIDTH / SCR_HEIGHT                 'aspect = x/y
    znear = 1                                       'Near clip
    zfar = 500                                      'far clip

    'use glu Perspective to set our 3d frustum dimension up
	gluPerspective FOVy, aspect, znear, zfar

    'Modelview mode
    'ie. Matrix that does things to anything we draw
    'as in lines, points, tris, etc.
	glMatrixMode GL_MODELVIEW
	'load identity(clean) matrix to modelview
	glLoadIdentity

	glShadeModel GL_SMOOTH                 'set shading to smooth(try GL_FLAT)
	glClearColor 0.0, 0.0, 0.0, 0.0        'set Clear color to BLACK
	glClearDepth 1.0                       'Set Depth buffer to 1(z-Buffer)
	glEnable GL_DEPTH_TEST                 'Enable Depth Testing so that our z-buffer works

	'compare each incoming pixel z value with the z value present in the depth buffer
	'LEQUAL means than pixel is drawn if the incoming z value is less than
    'or equal to the stored z value
	glDepthFunc GL_LEQUAL
	
	glBlendFunc GL_SRC_ALPHA,GL_ONE     'for gl Font

    'have one or more material parameters track the current color
    'Material is your 3d model
	glEnable GL_COLOR_MATERIAL


    glEnable GL_TEXTURE_2D
	'Tell openGL that we want the best possible perspective transform
	glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST

END SUB


'*******************************************************************************************
'Check for events from SDL
'Params: Escapeval is a byref integer that allows us to
'       quit out mainloop and qui the proggie

Sub SDL_GetEvents(EscapeVal as Integer)
  'SDL event is type in the SDL inc directory
  dim event as SDL_Event

        'poll events
		while( SDL_PollEvent ( @event ) )
			select case event.type
				case SDL_KEYDOWN:               'if a key is pressed quit proggie
				    'EscapeVal = -1
				case SDL_MOUSEBUTTONDOWN:
			end select
		wend
End Sub

'*******************************************************************************************
'Draw to our open GL screen

Sub draw_scene(vb as Model3d ptr)
    'clear the screen
    'GL_COLOR_BUFFER_BIT = to black(remember glClearColor?)
    'GL_DEPTH_BUFFER_BIT set depth buffer to 1 (remember glClearDepth?)
    glClear  GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT

    glPushMatrix
	glLoadIdentity

	'// Give openGL our camera position, then camera view, then camera up vector
    gluLookAt Camera.m_Position.x, Camera.m_Position.y, Camera.m_Position.z,_
              Camera.m_Target.x,   Camera.m_Target.y,   Camera.m_Target.z,_
              Camera.m_Up.x,       Camera.m_Up.y,       Camera.m_Up.z


	glScalef scaleValue, scaleValue * HEIGHT_RATIO, scaleValue

    glBindTexture GL_TEXTURE_2D, @TextID(0)

    glEnableClientState  GL_VERTEX_ARRAY
	glEnableClientState  GL_TEXTURE_COORD_ARRAY

	glVertexPointer  3, GL_FLOAT, 0, vb->m_pVertex
    glTexCoordPointer  2, GL_FLOAT, 0, vb->m_pTexCoord

    glDrawArrays  GL_TRIANGLES, 0, vb->m_nVertices

    glDisableClientState GL_VERTEX_ARRAY
    glDisableClientState GL_TEXTURE_COORD_ARRAY

    glPopMatrix
    
    glColor3f 1.0, 0.5, 1.0
	glPrint 0,460,"FPS/VA :  " + str$(FPS2), 1
	glColor4f 1.0, 1.0 ,1.0, 1.0

    glFlush
end sub


sub Init_Texture( hMap as SDL_Surface ptr, htexture() as ubyte)


    hMap = SDL_LoadBMP(Path+"hmap24.bmp")
    if hMap = 0  then
	   SDL_FreeSurface hMap
	   SDL_Quit
	   screen 13
	   print "error"
	   sleep
	   end -1
	end if

	dim imgptr as ubyte ptr
    imgptr = hMap->pixels

    dim i as integer
    dim x as integer, y as integer

	for y = 0 to hMap->h - 1
	   for x = 0 to hMap->w - 1
  			hTexture(x +  (y * hMap->w)) = *(imgptr + (x + (y * hMap->w)) * 3 + 1)
  	   next x
    next y

    SDL_FreeSurface hMap


end sub




function Height(byval X as integer,byval Y as integer) as integer

    dim x2 as integer, y2 as integer
	x2 = X mod TEXT_XMAX								'// Error Check Our x Value
	y2 = Y mod TEXT_XMAX								'// Error Check Our y Value

	Height = Texture(x2 + (y2 * TEXT_XMAX))				'// Index Into Our Height Array And Return The Height

end function

function RenderHeightMap() as Model3d ptr


	dim xc as integer
	dim yc as integer
    dim x as integer
	dim y as integer
	dim z as integer
	dim u as single
	dim v as single
	dim ntri as integer
	dim index as integer

    dim vb as  model3d ptr

	vb = allocate(len(model3d))


    vb->m_nVertices =  (TEXT_XMAX * TEXT_YMAX * 6) / ( STEP_SIZE ^ 2)
    vb->m_pVertex = allocate(len(GLfloat)* vb->m_nVertices * 3)
    vb->m_pTexCoord = allocate(len(GLfloat)* vb->m_nVertices * 2)

    index = 0

	glBegin GL_TRIANGLES


    for  yc = 0 to (TEXT_YMAX-STEP_SIZE) - 1 step STEP_SIZE
		 for  xc = 0  to  (TEXT_XMAX-STEP_SIZE) - 1 step STEP_SIZE

 			for nTri = 0 to 5
				if (nTri = 1) or (nTri = 2) or (nTri = 5) then
                    x = xc + STEP_SIZE
                else
                    x = xc + 0
                end if
                if (nTri = 2) or (nTri = 4) or (nTri = 5) then
                    z = yc + STEP_SIZE
                else
                    z = yc + 0
                end if

                y = Height(x,z)

       			u = x / TEXT_XMAX
    			v = z / TEXT_YMAX
       			'glTexCoord2f  u, v
     			'glVertex3i x - (TEXT_XMAX/2) , y - (TEXT_YMAX/2), z - (TEXT_XMAX/2)

     			vb->m_pVertex[index * 3 + 0] = x - (TEXT_XMAX/2)
     			vb->m_pVertex[index * 3 + 1] = y - (TEXT_XMAX/2)
     			vb->m_pVertex[index * 3 + 2] = z - (TEXT_XMAX/2)


     			vb->m_pTexcoord[index * 2 + 0] = u
     			vb->m_pTexcoord[index * 2 + 1] = v

     			index = index + 1

			next ntri

		next xc
	next yc
	glEnd

RenderHeightMap = vb

end Function



'//*****************************************************************************************
'//*****************************************************************************************
'CAMERA STUFF
'//*****************************************************************************************
'//*****************************************************************************************

sub vector_cross (v1 as vector3d, v2 as vector3d, vout as vector3d)
    vout.x = (v1.y * v2.z) - (v2.y * v1.z)
    vout.y = (v1.z * v2.x) - (v2.z * v1.x)
    vout.z = (v1.x * v2.y) - (v2.x * v1.y)
end sub

function vector_magnitude(v as vector3d) as single
    dim mag as single
    mag = sqr(v.x * v.x + v.y * v.y + v.z * v.z)
    if mag = 0 then mag = 1
    vector_magnitude = mag
end function

sub vector_normalize (v as vector3d)
    dim mag as single
    mag = vector_magnitude(v)
    v.x = v.x / mag
    v.y = v.y / mag
    v.z = v.z / mag
end sub


sub vector_add (v1 as vector3d, v2 as vector3d, vout as vector3d)
    vout.x = v1.x + v2.x
    vout.y = v1.y + v2.y
    vout.z = v1.z + v2.z
end sub

sub vector_sub (v1 as vector3d, v2 as vector3d, vout as vector3d)
    vout.x = v1.x - v2.x
    vout.y = v1.y - v2.y
    vout.z = v1.z - v2.z
end sub



sub camera_set_position(Byref Camera as CameraType, _
                        byval px as single, byval py as single, byval pz as single,_
                        byval vx as single, byval vy as single, byval vz as single,_
                        byval ux as single, byval uy as single, byval uz as single)

    Camera.m_Position.x = px
    Camera.m_Position.y = py
    Camera.m_Position.z = pz

    Camera.m_Target.x = vx
    Camera.m_Target.y = vy
    Camera.m_Target.z = vz

    Camera.m_Up.x = ux
    Camera.m_Up.y = uy
    Camera.m_Up.z = uz


end sub


Sub camera_setview_by_mouse(Camera as CameraType)

    const MID_X = SCR_WIDTH  shr 1
    const MID_Y = SCR_HEIGHT  shr 1


    dim mouse_x as integer, mouse_y as integer
    dim angle_y as single
    dim angle_z as single
    static current_rot_x as single

    'get axis of rotation for roll_angle
    camera.m_Up.x = cos(camera.m_Roll * 3.141593 / 180)
    camera.m_Up.y = sin(camera.m_Roll * 3.141593 / 180)
    camera.m_Up.z = 0
    vector_normalize  camera.m_Up


    'Get the mouse's current X,Y position
    SDL_GetMouseState @mouse_x, @mouse_y

    ' cursor did not move
    if  (mouse_x = MID_X) and (mouse_y = MID_Y) then exit sub

    ' reset mouse pos to middle of screenmSet the mouse position to the middle of our window
    SDL_WarpMouse MID_X, MID_Y


    ' get the vector the mouse moved
    ' /1000 makes it move slowly
    angle_y = (MID_X - mouse_x)  / 1000.0
    angle_z = (MID_Y - mouse_y)  / 1000.0

    'restrict the cam
    current_rot_x = current_rot_x - angle_z

    ' Clamp values
    if current_rot_x > 1.0 then
        current_rot_x = 1.0
    elseif current_rot_x < -1.0 then
        current_rot_x = -1.0
    else
        'if current rotation is within range...


        'get forward vector by subtracting the pos from lookat
        dim v_right  as vector3d
        dim v_forward  as vector3d
        v_forward.x = camera.m_Target.x - camera.m_Position.x
        v_forward.y = camera.m_Target.y - camera.m_Position.z
        v_forward.z = camera.m_Target.z - camera.m_Position.x


        'right = forward x up
        'normalize to be sure
        vector_cross  v_forward , camera.m_Up, v_right
        vector_normalize  v_right



        ' Rotate around our perpendicular(right) axis
        camera_rotate_view Camera, angle_z, v_right.x, v_right.y, v_right.z

        'Set our up rotation using the camera.m_Up vector as axis of rotation
        'for roll angle
        camera_rotate_view Camera, angle_y, camera.m_Up.x, camera.m_Up.y, camera.m_Up.z


    end if

end sub


Sub camera_rotate_view (Byref Camera as CameraType, byval angle as single,_
                        byval x as single, byval y as single, byval z as single)

    dim v_new_view as vector3d
    dim v_view as vector3d

    ' Get the view vector (The direction we are facing) forward vector
    v_view.x = camera.m_Target.x - camera.m_Position.x
    v_view.y = camera.m_Target.y - camera.m_Position.y
    v_view.z = camera.m_Target.z - camera.m_Position.z

    ' Calculate the sine and cosine of the angle once
    dim cos_theta as single, sin_theta as single
    cos_theta = cos(angle)
    sin_theta = sin(angle)

    ' Find the new x position for the new rotated point
    v_new_view.x = (cos_theta + (1 - cos_theta) * x * x) * v_view.x
    v_new_view.x = v_new_view.x + ((1 - cos_theta) * x * y - z * sin_theta) * v_view.y
    v_new_view.x = v_new_view.x + ((1 - cos_theta) * x * z + y * sin_theta) * v_view.z

    ' Find the new y position for the new rotated point
    v_new_view.y = ((1 - cos_theta) * x * y + z * sin_theta) * v_view.x
    v_new_view.y = v_new_view.y + (cos_theta + (1 - cos_theta) * y * y)  * v_view.y
    v_new_view.y = v_new_view.y + ((1 - cos_theta) * y * z - x * sin_theta) * v_view.z

    ' Find the new z position for the new rotated point
    v_new_view.z = ((1 - cos_theta) * x * z - y * sin_theta)    * v_view.x
    v_new_view.z = v_new_view.z + ((1 - cos_theta) * y * z + x * sin_theta) * v_view.y
    v_new_view.z = v_new_view.z + (cos_theta + (1 - cos_theta) * z * z)     * v_view.z

    ' Now we just add the newly rotated vector to our position to set
    ' our new rotated view of our camera.
    camera.m_Target.x = camera.m_Position.x + v_new_view.x
    camera.m_Target.y = camera.m_Position.y + v_new_view.y
    camera.m_Target.z = camera.m_Position.z + v_new_view.z

end sub



Sub camera_move(Byref Camera as CameraType, byval speed as single)

    ' Get our view vector (The direciton we are facing)
    dim v_forward as vector3d
    v_forward.x = camera.m_Target.x - camera.m_Position.x
    v_forward.y = camera.m_Target.y - camera.m_Position.y
    v_forward.z = camera.m_Target.z - camera.m_Position.z

    vector_normalize  v_forward

    camera.m_Position.x = camera.m_Position.x + v_forward.x * speed
    camera.m_Position.y = camera.m_Position.y + v_forward.y * speed
    camera.m_Position.z = camera.m_Position.z + v_forward.z * speed

    camera.m_Target.x = camera.m_Target.x + v_forward.x * speed
    camera.m_Target.y = camera.m_Target.y + v_forward.y * speed
    camera.m_Target.z = camera.m_Target.z + v_forward.z * speed

end sub

Sub camera_strafe(Byref Camera as CameraType, byval speed as single)

    ' Get our view vector (The direciton we are facing)
    dim v_forward as vector3d
    dim v_right as vector3d

    v_forward.x = camera.m_Target.x - camera.m_Position.x
    v_forward.y = camera.m_Target.y - camera.m_Position.y
    v_forward.z = camera.m_Target.z - camera.m_Position.z

    'get the right vector so for moving left or right
    'normalizing it to make our movements scalable
    vector_cross  v_forward , camera.m_Up, v_right
    vector_normalize  v_right


    'strafe right or left depending on the value of the speed

    camera.m_Position.x = camera.m_Position.x + v_right.x * speed
    camera.m_Position.y = camera.m_Position.y + v_right.y * speed
    camera.m_Position.z = camera.m_Position.z + v_right.z * speed

    'unless you want to "lock" your target you should also update
    'the target vector
    'try to Rem the following lines just for kicks
    'hint: this could be used for 3rd person cams
    camera.m_Target.x = camera.m_Target.x + v_right.x * speed
    camera.m_Target.y = camera.m_Target.y + v_right.y * speed
    camera.m_Target.z = camera.m_Target.z + v_right.z * speed

end sub


'//*****************************************************************************************
'//*****************************************************************************************
'Terrain blrnder mesh
'//*****************************************************************************************
'//*****************************************************************************************


sub Load_Images(Hmap as SDL_Surface Ptr, ImageFinal as SDL_Surface Ptr)

    dim i as integer

    ImageFinal = SDL_LoadBMP(Path+"Terrain.bmp")
    if ImageFinal = 0  then
	   SDL_FreeSurface ImageFinal
	   SDL_Quit
	   screen 13
	   print "error"
	   sleep
	   end -1
	end if


    HMap = SDL_LoadBMP(Path+"hmap24inv.bmp")
    if hMap = 0  then
	   SDL_FreeSurface hMap
	   SDL_Quit
	   screen 13
	   print "error"
	   sleep
	   end -1
	end if

	dim ptrbyte as ubyte ptr
    dim itextsize as integer
    dim iptr as integer

    ptrByte = ImageFinal->Pixels
    iTextSize = (ImageFinal->W * ImageFinal->H * 3)-1
    for iPtr = 0 to iTextSize step 3
      swap *(ptrByte+iPtr),*(ptrByte+iPtr+2)
    next iPtr

    'NEW!!!
    'Create the texture
    glGenTextures 1, @TextID(0)

	'Typical Texture Generation Using Data From The Bitmap
	glBindTexture GL_TEXTURE_2D, @TextID(0)

    'Linear filtering mode
    glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR

    'Generate The Texture
    'from an SDL surface
	glTexImage2D GL_TEXTURE_2D, 0, 3, ImageFinal->W, ImageFinal->H, 0, GL_RGB, GL_UNSIGNED_BYTE, ImageFinal->pixels

    'Free the surface since we don't have use for it anymore
	SDL_FreeSurface ImageFinal




End sub


'//*****************************************************************************************
'//*****************************************************************************************
'Font Stuff
'//*****************************************************************************************
'//*****************************************************************************************


sub Load_Font_Texture()

	dim FileName$
	dim font_image as sdl_surface ptr



	FileName$ = "font24inv.bmp"
	font_image = SDL_LoadBMP(Path + Filename$)
	if font_image = 0  then
	   SDL_FreeSurface font_image
	   SDL_Quit
	   screen 13
	   print "error"
	   sleep
	   end -1
	end if

	'color corrector
	'Thanks to "the car"
    dim ptrbyte as ubyte ptr
    dim itextsize as integer
    dim iptr as integer

    ptrByte = font_image->Pixels
    iTextSize = (font_image->W * font_image->H * 3)-1
    for iPtr = 0 to iTextSize step 3
      swap *(ptrByte+iPtr),*(ptrByte+iPtr+2)
    next iPtr


	glGenTextures 1, @font_texture

	glBindTexture GL_TEXTURE_2D, @font_texture
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
	glTexImage2D GL_TEXTURE_2D, 0, 3, font_image->W, font_image->H, 0, GL_RGB, GL_UNSIGNED_BYTE, font_image->Pixels



    BuildFont

	SDL_FreeSurface font_image

end sub


sub BuildFont()

	dim cx as single
	dim cy as single
	dim floop as integer
	const FACTOR = 1/16

	fbase=glGenLists(256)								' Creating 256 Display Lists
	glBindTexture GL_TEXTURE_2D, @font_texture		    ' Select Our Font Texture
	for floop = 0 to 255
		cx=(floop mod 16) / 16.0						' X Position Of Current Character
		cy=(floop \ 16)   / 16.0						' Y Position Of Current Character

		glNewList fbase+floop,GL_COMPILE				' Start Building A List
			glBegin GL_QUADS							' Use A Quad For Each Character
				glTexCoord2f cx, (1 - cy) - FACTOR		' Texture Coord (Bottom Left)
				glVertex2i 0,0							' Vertex Coord (Bottom Left)
				glTexCoord2f cx + FACTOR ,(1 - cy) - FACTOR ' Texture Coord (Bottom Right)
				glVertex2i 16,0						 		' Vertex Coord (Bottom Right)
				glTexCoord2f cx + FACTOR ,1 - cy			' Texture Coord (Top Right)
				glVertex2i 16,16							' Vertex Coord (Top Right)
				glTexCoord2f cx,1 - cy						' Texture Coord (Top Left)
				glVertex2i 0,16								' Vertex Coord (Top Left)
			glEnd											' Done Building Our Quad (Character)
			glTranslatef 16,0,0								' Move To The Right Of The Character
		glEndList											' Done Building The Display List
	next floop

end sub

sub KillFont()

	glDeleteLists fbase,256

end sub

sub glPrint(byval x as GLint, byval  y as GLint, byref xstring  as string , byval xset as integer)	'// Where The Printing Happens

	dim leng as integer
	leng = len(xstring)
	dim somestring as byte ptr
	somestring = strptr(xstring)
	dim i as integer
	dim chars(leng) as unsigned byte
	for i = 0 to Leng
		chars(i) = somestring[i] - 32
	next i


	if xset>1 then
		xset=1
	end if



	glBindTexture GL_TEXTURE_2D, @font_texture			' Select Our Font Texture
	glDisable GL_DEPTH_TEST								' Disables Depth Testing
	glMatrixMode GL_PROJECTION							' Select The Projection Matrix
	glPushMatrix 										' Store The Projection Matrix
	glLoadIdentity 										' Reset The Projection Matrix
	glOrtho 0,640,0,480,-1,1							' Set Up An Ortho Screen
	glMatrixMode GL_MODELVIEW							' Select The Modelview Matrix
	glPushMatrix 										' Store The Modelview Matrix
	glLoadIdentity 										' Reset The Modelview Matrix
	glTranslated x,y,0									' Position The Text (0,0 - Bottom Left)
    glEnable GL_BLEND
	glListBase fbase + (128*xset)					    ' Choose The Font Set (0 or 1)
	glCallLists Leng,GL_UNSIGNED_BYTE,@chars(0)  		' Write The Text To The Screen
	glDisable GL_BLEND
	glMatrixMode GL_PROJECTION							' Select The Projection Matrix
	glPopMatrix 										' Restore The Old Projection Matrix
	glMatrixMode GL_MODELVIEW							' Select The Modelview Matrix
	glPopMatrix 										' Restore The Old Projection Matrix
	glEnable GL_DEPTH_TEST								' Enables Depth Testing

end sub



