$TYPECHECK ON
$INCLUDE <RapidQ2.inc>
$INCLUDE <GL\QGL.inc>
dim debug as qdebug

'----------------------------------------------- 
'sample HeNe #19,'' This code was created by Jeff Molofee '99  
'' ported by JohnK 
'----------------------------------------------- 
DECLARE SUB drawGLScene
DECLARE Sub MakeQuad
DECLARE sub Form_Key_Press(keysym AS Word, KeyShift AS INTEGER)
DECLARE sub ResetParticle( byval num as integer, byval clr as integer, byval xDir as single, byval yDir as single, byval zDir as single )
DECLARE sub initfx
DECLARE sub sizeit
DECLARE sub wipeoff

'' Max number of particles 
    CONST MAX_PARTICLES = 250
    DEFINT rainbow = TRUE    '' Toggle rainbow effect                              
    DEFSNG slowdown = -1.0 '' Slow Down Particles                                
    DEFSNG xspeed          '' Base X Speed (To Allow Keyboard Direction Of Tail) 
    DEFSNG yspeed          '' Base Y Speed (To Allow Keyboard Direction Of Tail) 
    DEFSNG zoom = -10.0   '' Used To Zoom Out                                   
    DEFINT col = 0        '' Current Color Selection                            
    DEFINT delay          '' Rainbow Effect Delay                               

    '' Create our particle structure 
    type particle
        active as integer  '' Active (Yes/No) 
        life as single     '' Particle Life   
        fade as single     '' Fade Speed      
    
        r as single        '' Red Value       
        g as single        '' Green Value     
        b as single        '' Blue Value      
    
        x as single        '' X Position      
        y as single        '' Y Position      
        z as single        '' Z Position      
    
        xi as single       '' X Direction     
        yi as single       '' Y Direction     
        zi as single       '' Z Direction     
    
        xg as single       '' X Gravity       
        yg as single       '' Y Gravity       
        zg as single       '' Z Gravity       
    end type
    
    '' Rainbow of colors 
    DEFSNG colors(0 to 35) = { _
         1.0,  0.5,  0.5, _
    	 1.0,  0.75, 0.5, _
    	 1.0,  1.0,  0.5, _
    	 0.75, 1.0,  0.5, _
         0.5,  1.0,  0.5, _
    	 0.5,  1.0,  0.75, _
    	 0.5,  1.0,  1.0, _
    	 0.5,  0.75, 1.0, _
         0.5,  0.5,  1.0, _
    	 0.75, 0.5,  1.0, _
    	 1.0,  0.5,  1.0, _
    	 1.0,  0.5,  0.75}
    '' Our beloved array of particles 
    dim particles(0 to MAX_PARTICLES-1) as particle 



'create our wrapper 
DIM GL AS QGL
DIM myTexture AS GLuint :myTexture = 0
DIM TheQuad as glInt

create tmx as QTimer
  interval = 1
  enabled  = 0
  onTimer  = drawGLScene
end create

' user interface 
create fx as QFORM
  caption = "RQGL Demo"
  top     = 16
  left    = 26
  width   = 640
  height  = 480
  onPaint    = drawGLScene
  onResize   = sizeit
  onClick    = wipeoff
  onKeyDown  = Form_Key_Press
  onShow     = initfx
end create
' main program 
fx.ShowModal
end



'user procedures 
sub initfx
    DIM clr as integer
    DIM i as integer
    dim xi as single , yi as single , zi as single 

    GL.Init(fx)
    '' Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit 
    myTexture = GL.CreateTextureFromFile("particle.bmp")
    IF myTexture = 0 THEN Showmessage "failed texture": fx.Close
    GL.Front = .1
    GL.Back = 200
    '' Enable smooth shading 
    glShadeModel( GL_SMOOTH )
    '' Set the background black 
    glClearColor( 0.2, 0.2, 0.2, 0.0 )
    '' Depth buffer setup 
    glClearDepth( 1.0 )
    '' Enables Depth Testing 
    glDisable( GL_DEPTH_TEST )
    '' Enable Blending 
    glEnable( GL_BLEND )
    '' Type Of Blending To Perform 
    glBlendFunc( GL_SRC_ALPHA, GL_ONE )

    '' Really Nice Perspective Calculations 
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST )
    '' Really Nice Point Smoothing 
    glHint( GL_POINT_SMOOTH_HINT, GL_NICEST )
    '' Enable Texture Mapping 
    glEnable( GL_TEXTURE_2D )
    '' Select Our Texture 
'    glBindTexture( GL_TEXTURE_2D, myTexture ) 
    '' Reset all the particles 
    for i = 0 to MAX_PARTICLES-1
        clr = ( i + 1 ) \ ( MAX_PARTICLES \ 12 )
	    xi = ( ( rnd * 50 ) - 26.0 ) * 10.0
	    yi = ( ( rnd * 50 ) - 25.0 ) * 10.0
	    zi =  yi
	    ResetParticle( i, clr, xi, yi, zi )
    next i
    MakeQuad
    tmx.enabled = true
end sub


sub sizeit
    GL.Resize(fx.clientWidth, fx.clientHeight)
    glMatrixMode( GL_MODELVIEW )            '' Reset The View 
    glLoadIdentity
end sub


sub wipeoff
    '' Clean up our textures 
   glDeleteTextures( 1, myTexture)
   GL.Close
   fx.close
end sub



'' function to reset one particle to initial state 
'' NOTE: I added this function to replace doing the same thing in several 
'' places and to also make it easy to move the pressing of numpad keys 
'' 2, 4, 6, and 8 into handleKeyPress function. 
sub ResetParticle( byval num as integer, byval clr as integer, byval xDir as single, byval yDir as single, byval zDir as single )
    '' Make the particels active 
    particles(num).active = TRUE
    '' Give the particles life 
    particles(num).life = 1.0
    '' Random Fade Speed 
    particles(num).fade = ( rnd * 100 ) / 1000.0 + 0.003
    '' Select Red Rainbow Color 
    particles(num).r = colors(clr * 3 + 0)
    '' Select Green Rainbow Color 
    particles(num).g = colors(clr * 3 + 1)
    '' Select Blue Rainbow Color 
    particles(num).b = colors(clr * 3+ 2)
    '' Set the position on the X axis 
    particles(num).x = 0.0
    '' Set the position on the Y axis 
    particles(num).y = 0.0
    '' Set the position on the Z axis 
    particles(num).z = 0.0
    '' Random Speed On X Axis 
    particles(num).xi = xDir
    '' Random Speed On Y Axi 
    particles(num).yi = yDir
    '' Random Speed On Z Axis 
    particles(num).zi = zDir
    '' Set Horizontal Pull To Zero 
    particles(num).xg = 0.0
    '' Set Vertical Pull Downward 
    particles(num).yg = -0.8
    '' Set Pull On Z Axis To Zero 
    particles(num).zg = 0.0

end sub

'' function to handle key press events 
sub Form_Key_Press(keysym AS Word, KeyShift AS INTEGER)
    dim i as integer

'showmessage str$(keysym) 

    select case keysym
	case 27    	    '' ESC key was pressed 
	    wipeoff
	
 	case 112 	    '' F1 key  toggles fullscreen mode 
 	    IF GL.FullScreen = False THEN 
            fx.BorderStyle = bsNone
            fx.top=0: fx.Left = 0
            SizeIt
            GL.FullScreen = True
        ELSE 
            fx.BorderStyle = bsSizeable
            fx.top=10: fx.Left = 10
            GL.FullScreen = False
        END IF
	
	case 187    	    '' + speeds up the particles 
	    if ( slowdown > 1.0 ) then slowdown -= 0.1
	    
	case 189           '' - slows down the particles 
	    if ( slowdown < 4.0 ) then slowdown += 0.1
	
	case 33      	    '' PageUp key was pressed 
	    '' this zooms into the scene 
	    zoom = zoom + 0.5

	case 34  	    '' this zooms out of the scene 
	    zoom = zoom -0.5
	    
	case 38       	    '' up arrow increases the particles' y movement 
	    if ( yspeed < 200.0 ) then _
			yspeed += 4
	
	case 40      	    '' dn arrow decreases the particles' y movement 
	    if ( yspeed > -200.0 ) then _
			yspeed -= 4
	
	case 39             '' Right arrow key was pressed 
	    '' this increases the particles' x movement 
	    if ( xspeed < 200.0 ) then _
			xspeed += 4
	
	case 37             '' Left arrow key was pressed 
	    '' this decreases the particles' x movement 
	    if ( xspeed > -200.0 ) then _
			xspeed -= 4
	
	case 71            '' 'g' increase particles' y gravity 
	    for i = 0 to MAX_PARTICLES-1
			if ( particles(i).yg < 1.5 ) then particles(i).yg = particles(i).yg +0.5
		next i
	
	case 89           '' y decreases the particles' y gravity 
	    for i = 0 to MAX_PARTICLES-1
			if ( particles(i).xg > -1.5 ) then 	particles(i).xg = particles(i).xg -0.5
	    next i

	
	case 88            '' x increases the particles' x gravity 
	    for i = 0 to MAX_PARTICLES-1
			if ( particles(i).xg < 1.5 ) then particles(i).xg = particles(i).xg + 0.5
	    next i
	
	case 13
	    '' Return key was pressed 
        '' this toggles the rainbow color effect 
	    rainbow = not rainbow
	    delay = 5
	
	case 32
	    '' Spacebar was pressed 
	    '' this turns off rainbow-ing and manually cycles through colors 
	    rainbow = FALSE
	    delay = 0
	    col = ( col + 1 ) mod 12
	end select

    IF KeyShift THEN
 	    '' Tab key was pressed 
 	    '' this resets the particles and makes them re-explode 
 	    for i = 0 to MAX_PARTICLES-1
 		   DEFINT clr = ( i + 1 ) \ ( MAX_PARTICLES \ 12 )
 		   DEFSNG xi, yi, zi
 		   xi = ( ( rnd * 50 ) - 26.0 ) * 10.0
 		   yi = ( ( rnd * 50 ) - 25.0 ) * 10.0
 		   zi = yi
 		   ResetParticle( i, clr, xi, yi, zi )
 		next i
    END IF
end sub



'' Here goes our drawing code 
SUB drawGLScene
    dim i as integer 
    dim x as single , y as single , z as single    
    dim xi as single , yi as single , zi as single    

    '' Clear The Screen And The Depth Buffer 
    glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT )
    glLoadIdentity

    '' Modify each of the particles 
    for i = 0 to MAX_PARTICLES-1
	    if ( particles(i).active ) then
		    x = particles(i).x		        ' Grab Our Particle X Position 
		    y = particles(i).y              ' Grab Our Particle Y Position 
		    z = particles(i).z + zoom     	' Particle Z Position + Zoom 

		    '' Draw The Particle Using Our RGB Values, 
		    '' Fade The Particle Based On It's Life 
 		    glColor4f( particles(i).r, _
 			       particles(i).g, _
 			       particles(i).b, _
 			       particles(i).life )

            glLoadIdentity
            glTranslatef(x, y, z)
            glCallList(theQuad)
		    '' Move On The X Axis By X Speed 
		    particles(i).x = particles(i).x + particles(i).xi / ( slowdown * 1000 )
		    '' Move On The Y Axis By Y Speed 
		    particles(i).y = particles(i).y + particles(i).yi / ( slowdown * 1000 )
		    '' Move On The Z Axis By Z Speed 
		    particles(i).z = particles(i).z + particles(i).zi / ( slowdown * 1000 )
		    '' Take Pull On X Axis Into Account 
		    particles(i).xi = particles(i).xi + particles(i).xg
		    '' Take Pull On Y Axis Into Account 
		    particles(i).yi = particles(i).yi + particles(i).yg
		    '' Take Pull On Z Axis Into Account 
		    particles(i).zi = particles(i).zi + particles(i).zg
		    '' Reduce Particles Life By 'Fade' 
		    particles(i).life = particles(i).life - particles(i).fade

		    '' If the particle dies, revive it 
		    if ( particles(i).life < 0.0 ) then
			    xi = xspeed + ( ( rnd * 60 ) - 32.0 )
			    yi = yspeed + ( ( rnd * 60 ) - 30.0 )
			    zi = ( ( rnd * 60 ) - 30.0 )
			    ResetParticle( i, col, xi, yi, zi )
            end if
		end if
	next i
    '' Draw it to the screen 
    GL.Flip
    '' Gather our frames per second 
    fx.Caption = "Frame Rate = " + str$(GL.FrameRate)
END SUB



Sub MakeQuad
    TheQuad = glGenLists( 1 )
    glNewList( TheQuad, GL_COMPILE)
		    '' Build Quad From A Triangle Strip 
		    glBegin( GL_TRIANGLE_STRIP )
		      '' Top Right 
		      glTexCoord2d( 1, 1 )
		      glVertex3f( 0.5, + 0.5, -10 )
		      '' Top Left 
		      glTexCoord2d( 0, 1 )
		      glVertex3f( -0.5,  + 0.5, -10 )
		      '' Bottom Right 
		      glTexCoord2d( 1, 0 )
		      glVertex3f( 0.5,  - 0.5, -10 )
		      '' Bottom Left 
		      glTexCoord2d( 0, 0 )
		      glVertex3f( -0.5, - 0.5, -10 )
		    glEnd
    glEndList
end sub