;; ----------------------------------------------------------------------------
;; Irrlicht Wrapper For Imperative Languages - Purebasic Examples
;; IrrlichtWrapper and FreeBasic-Example by Frank Dodd (2006)
;; Improved IrrlichtWrapper - Michael Taupitz (2007)
;; PureBasic-Examples by Michael Taupitz (neotoma) & Marius Eckardt (Thalius)
;; ----------------------------------------------------------------------------
;; Example 10 : Terrain And Fog
;; This example creates a terrain from a bitmap heightfield And displays it in
;; a foggy scene
;; ----------------------------------------------------------------------------
;;

XIncludeFile #PB_Compiler_Home + "Includes\PackerEx_IncludeV4.pb"

;; ////////////////////////////////////////////////////////////////////////////
;; Include the Irr3D-Requester
XIncludeFile "Irr3DRequester.pb"

;; ////////////////////////////////////////////////////////////////////////////
;; Global variables

; irrlicht objects
*terrain.irr_terrain
*TerrainNode.irr_node
*TerrainTexture0.irr_texture
*TerrainTexture1.irr_texture
*camera.irr_camera
*CameraNode.irr_node


#STONES = 5

#FS_PREFIX="myfs\"
#PASS = "crypt.me.for.example.in.irrlichtwrapper";

Global Dim explosion.l(26)

*SmokeTexture = #Null
*FireTexture = #Null
*RingTexture = #Null


shakeradius.f = 00

#SOUND = #True 

Structure sExternFS
  memory.l
  len.l
EndStructure

Structure sStone
  *node         ;Points to the SceneNOde (Meteor)
  *particle     ;Points to the Particle System
  *selector     ;Points to the Triangle-Selector
  state.l       ;Define the Stae (crashed or alive)
  *sound        ;The 'swish...'-Sound
EndStructure

;Place for the Stones, maybe usefull for later usage.
Dim stones.sStone(#STONES)

Declare setUpSmokeParticle(*stone.sStone)
Declare checkCollisions()
Declare renewStone(*stone.sStone)
DeclareCDLL.l FSCallback(*name, read_file.l, *efs.sExternFS)
Declare doExplosion(x.f, y.f, z.f )
; -----------------------------------------------------------------------------
; To Start the Irrlicht-Device we use the Irr3DRequester, to make it more comfortable
; for the Users, and also easier to test different resolutions and devices.
;If Irr3DRequester()
If  IrrStart( #IRR_EDT_DIRECT3D9, 640, 480, #IRR_WINDOWED, #IRR_NO_SHADOWS, #True)
  
  ;Add our CallBack-FileSystem
  IrrCreateCallbackFileSystem(@FSCallback())
  
  CompilerIf #SOUND
  IrrKlangStart()
  
  IrrklangAddCallbackFileSystem(@FSCallback()) ; Also for IrrKlang !!!
  
  IrrKLangSetSoundVolume(1.0)
  *back_sound = IrrKlangAddSound(#FS_PREFIX+"media\02_FallenHeros.ogg");,#IRRKLANG_ESM_AUTO_DETECT, #True)
  *explo_sound = IrrKlangAddSound(#FS_PREFIX+"media\explosion.wav");,#IRRKLANG_ESM_AUTO_DETECT, #True)
  *comet_sound = IrrKlangAddSound(#FS_PREFIX+"media\cometfly.wav");,#IRRKLANG_ESM_AUTO_DETECT, #True) 
  *bgs = IrrKLangPlay2D(*back_sound,#True, #True)
  If *bgs
    IrrKlangSoundSetVolume(*bgs, 0.5)
    IrrKlangSoundSetIsPaused(*bgs,#False)
  EndIf
  
  IrrKlangSoundSetMinDistance(*explo_sound, 5000.0)
  CompilerEndIf
  ; send the window caption
  IrrSetWindowCaption( "Example : Meteors " )
  
  ;  IrrSetTextureCreationFlag(#IRR_ETCF_ALWAYS_32_BIT, #True)
  IrrSetTextureCreationFlag(#IRR_ETCF_CREATE_MIP_MAPS , #False)
  ;  IrrSetTextureCreationFlag(#IRR_ETCF_OPTIMIZED_FOR_QUALITY,#True)
;   
   *cctt = IrrLoadCellTabledTexture(#FS_PREFIX+"media\explosion\explosion.bmp", 128, 128, 26, tableHeight.l=1)
;   
;   
   For i = 0 To 25
;     
;      explosion(i) = IrrGetTexture("media\explosion\explosion_00"+RSet(Str(i+1),2,"0")+".jpg")
     explosion(i) = IrrGetCellTabledTexture(*cctt, i, 0)
   Next
  
  *SmokeTexture = IrrGetTexture( #FS_PREFIX+"media\ParticleGrey.bmp" )
  *FireTexture = IrrGetTexture( #FS_PREFIX+"media\Fire.bmp" )
  *RingTexture = IrrGetTexture( #FS_PREFIX+"media\Particle-011x.png" )
  *Smoke2Texture = IrrGetTexture( #FS_PREFIX+"media\Smoke.png"         ) ;Smoke.png  
  
  ; here we create the terrain from a greyscale bitmap where bright pixels are
  ; high points and black pixels are low points. the command generates the mesh
  ; and automatically adds it as a node to the scene
;  *terrain = IrrAddTerrain( "media\terrain-heightmap.bmp" )

  *terrain = IrrAddTerrain( #FS_PREFIX+"media\curvy.bmp" )


; *heightmap = ?heightmap_start
; len = (?heightmap_end-?heightmap_start)
; Debug("hm="+Str(*heightmap)+" / len="+Str(len))
; 
; *terrain = IrrAddTerrainRAWFromMemory( ?heightmap_start, (?heightmap_end-?heightmap_start), 32)
  
  ; the node is too small to be a proper terrain so we get the node object of the
  ; terrain and scale its size up 40 times along the X and Z axis and just 4 times
  ; along the Y axis
  *TerrainNode = *terrain
;  IrrSetNodeScale( *TerrainNode, 40.0, 80, 40.0 )
  IrrSetNodeScale( *TerrainNode, 40.0, 7, 40.0 )
  
  ; we load two textures in to apply to the terrain node
;   *TerrainTexture0 = IrrGetTexture( "media\terrain-texture.jpg" )

   *TerrainTexture0 = IrrGetTexture( #FS_PREFIX+"media\alien_output.bmp" )
;   *TerrainTexture1 = IrrGetTexture( "media\detailmap3.jpg" )

;  *TerrainTexture0 = IrrGetTexture( "media\ColorLayer.bmp" )
  *TerrainTexture1 = IrrGetTexture( #FS_PREFIX+"media\DetailLayer1.bmp" )



  
  ; the first texture is a color texture that is applied across the entire
  ; surface of the map. this needs to be a fairly high resoloution as the map is
  ; very large now
  IrrSetNodeMaterialTexture( *TerrainNode, *TerrainTexture0, 0 )
  
  ; the second texture is tiled many times across the map this adds fine detail
  ; and structure to the first enlarged terain color
  IrrSetNodeMaterialTexture( *TerrainNode, *TerrainTexture1, 1 )
  
  ; we set the scale of the detail map so its repeated 20 times across the map in
  ; the x and y axis
  IrrScaleTexture( *terrain, 1.0, 1.0 )
  
  ; finally we apply some material texuring effects to the node
  ; the terrain is self illuminating
  IrrSetNodeMaterialFlag( *TerrainNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  ; the material type is detail type. this type applies the first texture across
  ; the entire node and then scales and applies the second texture across the node
  ; there are many different material types you can set, these can be found in the
  ; .bi definition file, experiment with them
  IrrSetNodeMaterialType ( *TerrainNode, #IRR_EMT_DETAIL_MAP )
  
  ; finally we switch on fog for this material so that this terrain will fade out
  ; into a fog in the distance
  IrrSetNodeMaterialFlag( *TerrainNode, #IRR_EMF_FOG_ENABLE, #IRR_ON )
  
  ; now we need to add the fog to the scene. the first three parameters are the
  ; fog color, we set this to the same color as our sky so the scene fogs out
  ; nicely into nothing, the next parameter specifies whether you want the fog
  ; to increase in a linear mannar or exponentially - exponential fog usually
  ; looks more atmospheric while linear looks more like a dense sea fog, the next
  ; two parameters specify the distance at which the fog starts and the distance
  ; at which the fog reaches its maximum density and finally the fog density -
  ; this is only used with exponential fog and determines how quickly the
  ; exponential change takes place
  ;  IrrSetFog ( 128,240,255,255, #IRR_EXPONENTIAL_FOG, 0.0,8000.0, 0.5 )
  IrrSetFog ( 128,64,64,64, #IRR_EXPONENTIAL_FOG, 0.0,8000.0, 0.5 )
  
  
  ; we add a first person perspective camera to the scene so you can look about
  ; and move it into the center of the map
  ;*camera = IrrAddCamera(0,0,0,0,0,0)
  
  *camera = IrrAddFPSCamera()
  *CameraNode = *camera
  IrrSetNodePosition( *CameraNode, 3942.8, 1102.7, 5113.9 )
  IrrSetNodeRotation( *CameraNode, 19, -185.5, 0 )
  
  ; the clipping distance of a camera is a distance beyond which no triangles are
  ; rendered, this speeds the scene up by not showing geometry that is in the
  ; distance and too small to see however our terrain is so huge we need to
  ; extend this distance out
  IrrSetCameraClipDistance( *camera, 12000 )
  
  
;   *TerrainCollision = IrrGetCollisionGroupFromTerrain(*TerrainNode,3)
;   *ret = IrrAddCollisionAnimator( *TerrainCollision, *CameraNode, 30.0,30.0,30.0, 0.0,-1.0,0.0, 0.0,50.0,0.0 )
  
  ; now we set up some meteors
  
  ;add some Rocks in the Scene....
  ;this is to make this little exmaple a little bit nicer. Also you can see how easy it is
  ;to add Objects with autmatic movement.
  ;Load the Mesh and Texture for the meteorites
  *stone_mesh = IrrGetMesh(#FS_PREFIX+"media\stone1.ms3d")
  *stone_texture = IrrGetTexture(#FS_PREFIX+"media\stone1.jpg")
  
  
  IrrTerrainGetCenter(*TerrainNode, @tc_X.f, @tc_y.f, @tc_z.f)
  
  For i = 0 To #STONES-1
    renewStone(@stones(i))
    
  Next
  
  
  ;now we try a SkyDome....
  *SkyTex = IrrGetTexture(#FS_PREFIX+"media\skysphere.png")
  *SkyDome = IrrAddSkyDomeToScene(*SkyTex, 16,8, 0.5,2)
  IrrAddRotationAnimator(*SkyDome, 0,0.005,0)
  
  
  ;Staff our Skybox with textures, so it looks like be in space.....
  ;   Dim *textures.irr_texture(6)
  ;   *textures(0) = IrrGetTexture("media\up_256x256.jpg")
  ;   *textures(1) = IrrGetTexture("media\down_256x256.jpg")
  ;   *textures(2) = IrrGetTexture("media\left_256x256.jpg")
  ;   *textures(3) = IrrGetTexture("media\right_256x256.jpg")
  ;   *textures(4) = IrrGetTexture("media\front_256x256.jpg")
  ;   *textures(5) = IrrGetTexture("media\back_256x256.jpg")
  ;
  ;   *SkyBox = IrrAddSkyBoxToScene( *textures(0),*textures(1),*textures(2),*textures(3),*textures(4),*textures(5))
  
  
  ;  IrrFXCreateNightVision(*CameraNode,"media/noise.jpg",128)
  ;  IrrFXCreateDreamFilter(*CameraNode)
  
  
 ;   IrrFXCreateGlow(*CameraNode)
  
  
  
  ; we also hide the mouse pointer to see the view better
  ;IrrHideMouse()
  
  ; -----------------------------------------------------------------------------
  ; while the irrlicht environment is still running
  While IrrRunning()
    ; begin the scene, erasing the canvas with sky-blue before rendering
    IrrBeginScene( 240, 255, 255 )
    
    ;      IrrFXRenderNightVision()
    ;      IrrFXRenderDreamFilter()
    
;         IrrFXRenderGlow()
    
    ; draw the scene
    IrrDrawScene()
    
    
    ; end drawing the scene and render it
    IrrEndScene()
    
    ;          IrrGetNodePosition(*camera,@x.f,@y.f,@z.f)
    ;          IrrTerrainHeight(*TerrainNode,x,z,@Height.f)
    ;Debug("Height="+StrF(Height)+" (Cam x="+StrF(x)+",y="+StrF(y)+",z="+StrF(z)+")")
    
    fps = IrrGetFPS()
    If fps <> lastFPS
      IrrSetWindowCaption("Example : Meteors  FPS:" + Str(fps) )
      lastFPS = fps;
    EndIf
    
    	; SHAKE CAMERA
    	
    ; 	  cx.f = shakeradius-(Random(shakeradius*100)/100)/2
    ; 	  cy.f = (Random(shakeradius*100)/100)/2
    ; 	  cz.f = shakeradius-(Random(shakeradius*100)/100)/2
    ;
    IrrGetNodePosition(*camera,@x.f,@y.f,@z.f)
    ;     IrrSetNodePosition(*camera,cx+x,y+cy,cz+z)
    ;
    ; 	  ; SLOW OUT SHAKING
    ; 	  If shakeradius > 0
    ; 		  shakeradius = shakeradius - 0.05; * delta
    ; 	  Else
    ; 		  shakeradius = 0
    ; 	  EndIf
    
    
    
    ;  // get the up vector
    ;    core::vector3df upwards(0.f, 1.f, 0.f);
    ;    getAbsoluteTransformation().rotateVect(upwards);
    ;
    ;    // And forward vector
    ;    core::vector3df forwards(0.f, 0.f, 1.f);
    ;    getAbsoluteTransformation().rotateVect(forwards);
    ;
    ;    // do doppler
    ;    const f32 elapsed = (timeMs - PreviousTime) / 1000.f;
    ;    PreviousTime = timeMs;
    ;
    ;    // do position/velocity
    ;    const core::vector3df position = getAbsolutePosition();
    ;    const core::vector3df velocity = (position - PreviousPosition) / elapsed;
    ;    PreviousPosition = position;
    ;
    ;    // feed position, velocity And orientation information To sound engine
    ;SoundEngine->setListenerPosition(position, forwards, velocity, upwards);
    ;
    
    
;    IrrKlangListenerPosition(x,y,z, 0,0,1,0,0,0,0,0,0);
    
    
    
    checkCollisions()
  Wend
  
  ; -----------------------------------------------------------------------------
  ; Stop the irrlicht engine and release resources
  CompilerIf #SOUND 
  IrrKlangStop()
  CompilerEndIf
  
  IrrStop()
EndIf


End


Procedure setUpSmokeParticle(*stone.sStone)
  Shared *SmokeTexture
  Shared *FireTexture
  Shared *comet_sound
  
  
  Define SmokeEmitter.IRR_PARTICLE_EMITTER
  Define FireEmitter.IRR_PARTICLE_EMITTER
  
  ; add a particle system to the irrlicht scene manager, a default emitter is not
  ; created as we will define out own. the particle system is blank at the moment
  *stone\Particle = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
  ; when the particle system starts it creates objects similar to billboards,
  ; this command specifies how large each of those particles will be
  
  IrrSetNodePosition( *stone\Particle, 0,30,0)
  
  ; here we define the particle emitter, a particle emitter is a mechanism that
  ; creates the particles over time and destroys them when their lifetime runs
  ; out. The parameters include: a box that defines the volume in which particles
  ; are created - the larger the box the more diffuse the particle cloud, a
  ; direction that determines where the particles drift off too, a range that
  ; defines hoe many particles will be generated each second, a colour range that
  ; determines a random tint that is applied to the particles, a range that
  ; determines the lifespan of the particles - the large the values the longer
  ; and larger (and slower) your particle cloud will be and finally an angle that
  ; defines a cone around your direction that is the maximum deviation from the
  ; direction the particles can take - values here make your particles billow
  ; outward
  SmokeEmitter\min_box_x = -12
  SmokeEmitter\min_box_y = -10
  SmokeEmitter\min_box_z = -12
  SmokeEmitter\max_box_x = 12
  SmokeEmitter\max_box_y = 10
  SmokeEmitter\max_box_z = 12
  SmokeEmitter\direction_x = 0
  SmokeEmitter\direction_y = -0.26
  SmokeEmitter\direction_z = 0
  SmokeEmitter\min_paritlcles_per_second = 300
  SmokeEmitter\max_paritlcles_per_second = 700
  SmokeEmitter\min_start_color_red = 255
  SmokeEmitter\min_start_color_green = 255
  SmokeEmitter\min_start_color_blue = 255
  SmokeEmitter\max_start_color_red = 0
  SmokeEmitter\max_start_color_green = 0
  SmokeEmitter\max_start_color_blue = 0
  SmokeEmitter\min_lifetime = 600
  SmokeEmitter\max_lifetime = 1000
  SmokeEmitter\max_angle_degrees = 120
  
  FireEmitter\min_box_x = -20
  FireEmitter\min_box_y = 0
  FireEmitter\min_box_z = -20
  FireEmitter\max_box_x = 20
  FireEmitter\max_box_y = 5
  FireEmitter\max_box_z = 20
  FireEmitter\direction_x = 0
  FireEmitter\direction_y = -0.12
  FireEmitter\direction_z = 0
  FireEmitter\min_paritlcles_per_second = 180
  FireEmitter\max_paritlcles_per_second = 220
  FireEmitter\min_start_color_red = 255
  FireEmitter\min_start_color_green = 255
  FireEmitter\min_start_color_blue = 255
  FireEmitter\max_start_color_red = 255
  FireEmitter\max_start_color_green = 0
  FireEmitter\max_start_color_blue = 0
  FireEmitter\min_lifetime = 400
  FireEmitter\max_lifetime = 800
  FireEmitter\max_angle_degrees = 90
  
  
  
  ; finally we add this particle emitting object to the particle system
  *em.l = IrrAddParticleEmitter( *stone\Particle, @SmokeEmitter )
  
  IrrSetParticleSize( *stone\Particle, 105,105)
  ; an affector is a mechanism that alters the particles over time, the fade out
  ; affector gradually fades the particles out so they are invisible when they
  ; are deleted this lets them smoothly vanish instead of poping out of existence
  IrrAddFadeOutParticleAffector( *stone\Particle )
  
  ; another affector is the gravity affector, this adds a small amount of velocity
  ; to the particles each frame, although its called a gravity affector it can
  ; be used to push the particles in any direction so you can have drifting smoke
  ; bubbling fountains, etc ...
  IrrAddGravityParticleAffector ( *stone\Particle, 0.05, 0.05, 0.0 )
  
  ; at the moment the particles are simple grey squares and before we apply a
  ; material to them we need to get the particle system as a scene node
  ;;ParticlesNode = SmokeParticles
  
  ; load a grey smoke like image for the particle
  
  ; apply the texture to the particles system, this texture will now be drawn
  ; across each particles surface
  IrrSetNodeMaterialTexture( *stone\Particle, *SmokeTexture, 0 )
  
  ; out particle system is not affected by lighting so we make it self
  ; illuminating
  IrrSetNodeMaterialFlag( *stone\Particle, #IRR_EMF_LIGHTING, #IRR_OFF )
  
  ; as the particle texture has black borders, each overlapping particle would
  ; draw this blackness ontop of one another as a sharp egde they would look like
  ; a lot of solid squares instead of the transparent gas effect we are trying
  ; to created. so here we change the material type of the node - instead of
  ; drawing the node solidly onto the screen it is added onto the colour
  ; underneath itself so black doesnt change the color and white would build up
  ; top of the existing color until it completly saturates the pixel
  IrrSetNodeMaterialFlag( *stone\Particle, #IRR_EMF_ZWRITE_ENABLE, #False )
  IrrSetNodeMaterialType ( *stone\Particle, #IRR_EMT_TRANSPARENT_VERTEX_ALPHA  )
  
  IrrAddChildToParent( *stone\Particle, *stone\node)
  
  
  ;Fire me
  
  
  *particle = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
  ; when the particle system starts it creates objects similar to billboards,
  ; this command specifies how large each of those particles will be
  IrrSetParticleSize( *particle, 80.0, 100.0 )
  
  ; finally we add this particle emitting object to the particle system
  *em.l = IrrAddParticleEmitter( *particle, @FireEmitter )
  
  
  ; an affector is a mechanism that alters the particles over time, the fade out
  ; affector gradually fades the particles out so they are invisible when they
  ; are deleted this lets them smoothly vanish instead of poping out of existence
  IrrAddFadeOutParticleAffector( *particle )
  
  ; another affector is the gravity affector, this adds a small amount of velocity
  ; to the particles each frame, although its called a gravity affector it can
  ; be used to push the particles in any direction so you can have drifting smoke
  ; bubbling fountains, etc ...
  IrrAddGravityParticleAffector ( *particle, 0.05, 0.05, 0.0 )
  
  ; at the moment the particles are simple grey squares and before we apply a
  ; material to them we need to get the particle system as a scene node
  ;;ParticlesNode = SmokeParticles
  
  ; load a grey smoke like image for the particle
  *ParticleTexture = IrrGetTexture( #FS_PREFIX+"media\Fire.bmp" )
  
  ; apply the texture to the particles system, this texture will now be drawn
  ; across each particles surface
  IrrSetNodeMaterialTexture( *particle, *ParticleTexture, 0 )
  
  ; out particle system is not affected by lighting so we make it self
  ; illuminating
  IrrSetNodeMaterialFlag( *particle, #IRR_EMF_LIGHTING, #IRR_OFF )
  
  ; as the particle texture has black borders, each overlapping particle would
  ; draw this blackness ontop of one another as a sharp egde they would look like
  ; a lot of solid squares instead of the transparent gas effect we are trying
  ; to created. so here we change the material type of the node - instead of
  ; drawing the node solidly onto the screen it is added onto the colour
  ; underneath itself so black doesnt change the color and white would build up
  ; top of the existing color until it completly saturates the pixel
  ;  IrrSetNodeMaterialType ( *Particle, #IRR_EMT_TRANSPARENT_ADD_COLOR  )
  
  IrrSetNodeMaterialFlag( *particle, #IRR_EMF_ZWRITE_ENABLE, #False )
  IrrSetNodeMaterialType ( *particle, #IRR_EMT_TRANSPARENT_VERTEX_ALPHA  )
  
  IrrAddChildToParent( *particle, *stone\node)
  
  
  
  
  
EndProcedure


; Procedure createEmitter(w.l, h.l, d.l)
;   *emitter.IRR_PARTICLE_EMITTER




Procedure setUpRing(*stone.sStone, height.f)
  ;Debug("Ring")
  
  Shared *RingTexture
  Shared *FireTexture
  Shared *comet_sound
  ;  Shared explosion()
  
  
  Define FireEmitter.IRR_PARTICLE_EMITTER
  
  ; add a particle system to the irrlicht scene manager, a default emitter is not
  ; created as we will define out own. the particle system is blank at the moment
  *particle = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
  ; when the particle system starts it creates objects similar to billboards,
  ; this command specifies how large each of those particles will be
  IrrSetParticleSize( *particle, 175.0, 175.0 )
  
  
  FireEmitter\min_box_x = -12
  FireEmitter\min_box_y = 0
  FireEmitter\min_box_z = -12
  FireEmitter\max_box_x = 12
  FireEmitter\max_box_y = 5
  FireEmitter\max_box_z = 12
  
  FireEmitter\direction_x = 0.00
  FireEmitter\direction_y = 0.20
  FireEmitter\direction_z = 0.00
  FireEmitter\min_paritlcles_per_second = 800
  FireEmitter\max_paritlcles_per_second = 1000
  FireEmitter\min_start_color_red = 255
  FireEmitter\min_start_color_green = 255
  FireEmitter\min_start_color_blue = 255
  FireEmitter\max_start_color_red = 128
  FireEmitter\max_start_color_green = 64
  FireEmitter\max_start_color_blue = 0
  FireEmitter\min_lifetime = 150
  FireEmitter\max_lifetime = 600
  FireEmitter\max_angle_degrees = 25
  
  IrrAddFadeOutParticleAffector( *particle )
  ;  IrrAddRotationParticleAffector(*Particle, 50,0,0  ,0,0,0)
  ;  IrrAddCollisionParticleAffector(*particle, 0,0.0,0, 0,1,0)
  IrrAddGravityParticleAffector ( *particle, 0.00, -0.10, 0.00 )
  
  ; load a grey smoke like image for the particle
  IrrSetNodeMaterialTexture( *particle, *FireTexture, 0 )
  IrrSetNodeMaterialFlag( *particle, #IRR_EMF_LIGHTING, #IRR_OFF )
  IrrSetNodeMaterialFlag( *particle, #IRR_EMF_ZWRITE_ENABLE, #False )
  IrrSetNodeMaterialType ( *particle, #IRR_EMT_TRANSPARENT_VERTEX_ALPHA  )
  
  
  IrrGetNodePosition(*stone\node, @x.f,@y.f, @z.f)
  y = height
  ;Debug("At "+StrF(x)+","+StrF(y)+","+StrF(z))
  IrrSetNodePosition( *particle, x,y+20,z)
  
  ; finally we add this particle emitting object to the particle system
  *em.l = IrrAddParticleRingEmitter( *particle, @FireEmitter, 0,0,0, 200,20 )
  
; IrrAddTextureAnimator( *particle, 18,@explosion(),1000/18,#False )
   IrrAddAttractionParticleAffector(*particle , x,y,z, 700.0, #False, #True, #True, #True)

  IrrAddStopParticleAffector(*particle, 1000)
 
  
  ;  IrrAddChildToParent( *Particle, *stone\node)
  
  ; brocks
  
  
  FireEmitter\min_paritlcles_per_second = 30
  FireEmitter\max_paritlcles_per_second = 70
  FireEmitter\direction_x = 1.80
  FireEmitter\direction_y = 0.40
  FireEmitter\direction_z = 0.80
  FireEmitter\max_angle_degrees = 90
  FireEmitter\max_start_color_red = 255
  FireEmitter\max_start_color_green = 128
  FireEmitter\max_start_color_blue = 0
  FireEmitter\min_lifetime = 1000
  FireEmitter\max_lifetime = 1000
  
  
  *particle = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
  ; when the particle system starts it creates objects similar to billboards,
  ; this command specifies how large each of those particles will be
  IrrSetParticleSize( *particle, 75.0, 75.0 )
  
  
  
  ;  IrrAddFadeOutParticleAffector( *Particle )
  IrrAddRotationParticleAffector(*particle, 50,0,0  ,0,0,0)
  ;  IrrAddCollisionParticleAffector(*particle, 0,0.0,0, 0,1,0)
  IrrAddGravityParticleAffector ( *particle, 0.00, -1.30, 0.00 )
  
  ; load a grey smoke like image for the particle
  IrrSetNodeMaterialTexture( *particle, *RingTexture, 0 )
  IrrSetNodeMaterialFlag( *particle, #IRR_EMF_ZWRITE_ENABLE, #False )
  IrrSetNodeMaterialFlag( *particle, #IRR_EMF_LIGHTING, #IRR_OFF )
  IrrSetNodeMaterialType ( *particle, #IRR_EMT_TRANSPARENT_ALPHA_CHANNEL  )
  
  
  IrrGetNodePosition(*stone\node, @x.f,@y.f, @z.f)
  y=height
  ;  Debug("At "+StrF(x)+","+StrF(y)+","+StrF(z))
  IrrSetNodePosition( *particle, x,y,z)
  
  ; finally we add this particle emitting object to the particle system
  *em.l = IrrAddParticleEmitter( *particle, @FireEmitter )
  
  IrrAddStopParticleAffector(*particle, 1000)
  
  
  
  
  ; nun noch ein kleines 'feuerwerk'
  ;
  
  doExplosion(x,y+100,z)
  
  ; *bill = IrrAddBillBoardToScene(600,600,  x,y+100,z)
  ; IrrSetNodeMaterialTexture( *bill,explosion(0), 0 )
  ; IrrAddTextureAnimator( *bill, 26,@explosion(),1000/26,#False )
  ; IrrSetNodeMaterialFlag( *bill, #IRR_EMF_ZWRITE_ENABLE, #False )
  ; IrrSetNodeMaterialFlag( *bill, #IRR_EMF_LIGHTING, #IRR_OFF )
  ; IrrSetNodeMaterialType( *bill, #IRR_EMT_TRANSPARENT_ADD_COLOR )
  ; 
  ; IrrAddDeleteAnimator(*bill, 900)
  
EndProcedure


Procedure renewStone(*stone.sStone)
  Shared *stone_mesh,*stone_texture,*TerrainNode
  Shared *comet_sound
  IrrTerrainGetCenter(*TerrainNode, @tc_X.f, @tc_y.f, @tc_z.f)
  
  If *stone\Particle <> 0
    ;     IrrAddStopParticleAffector(*stone\particle, 200)
    IrrAddStopParticleAffector(*stone\Particle, 1)
  EndIf
  If *stone\node <> 0
    IrrAddDeleteAnimator(*stone\node, 1000)
  EndIf
  
  rx.f = tc_X+(5000-Random(10000))/2
  ry.f = 10000+((5000-Random(10000))/2)
  rz.f = tc_z+(5000-Random(10000))/2
  *stone\node = IrrAddMeshToScene(*stone_mesh)
  *stone\state = #True
  
  *stone\selector = IrrGetCollisionGroupFromBox(*stone)
  setUpSmokeParticle(*stone)
  IrrSetNodePosition(*stone\node,rx,ry,rz)
  
  IrrSetNodeScale(*stone\node,0.5,0.5,0.5)
  
  
  
  IrrSetNodeMaterialTexture(*stone\node,*stone_texture,0)
  IrrSetNodeMaterialType(*stone\node, #IRR_EMT_SOLID)
  IrrSetNodeMaterialFlag(*stone\node, #IRR_EMF_LIGHTING, #IRR_OFF )
  
  
  IrrAddFlyStraightAnimator(*stone\node, rx,ry,rz, tc_X+((5000-Random(10000))/2),-10, 5000- (Random(5000)/2),tc_z+((5000-Random(10000))/2) , #True)
  
  ;Colour the stones ab bit
  ;    IrrSetNodeAllMaterialEmissiveColor(*stone\node,255,Random(255),Random(255),Random(255))
  
  
  CompilerIf #SOUND 
  *stone\sound = IrrKlangPlay3D(*comet_sound, rx,ry,rz, #True, #True, #False)
  If *stone\sound
    IrrKlangSoundSetVolume(*stone\sound, 1.0)
    IrrKlangSoundSetMaxDistance(*stone\sound,6000.0)
    IrrKlangSoundSetMinDistance(*stone\sound,2000.0)
    IrrKlangSoundSetIsPaused(*stone\sound,#False)
  Else
    Debug("Comet="+Str(*comet_sound))
  EndIf
  CompilerEndIf
  
  
EndProcedure



Procedure checkCollisions()
  Shared *TerrainCollision
  Shared *TerrainNode
  Shared shakeradius.f
  Shared stones.sStone()
  Shared *camera, *explo_sound
  For i = 0 To #STONES-1
    ;First an simple we check against the base......
    
    IrrGetNodePosition(stones(i)\node,@x.f,@y.f,@z.f)
    IrrTerrainHeight(*TerrainNode,x,z,@height.f);
    If y<=height
      setUpRing(@stones(i),height)
      renewStone(@stones(i))
      shakeradius = 2.0
      
      CompilerIf #SOUND 
      *bumm = IrrKlangPlay3D(*explo_sound, x,y,z, #False, #True, #False)
      
      IrrKlangSoundSetVolume(*bumm, 1.0)
      IrrKlangSoundSetMaxDistance(*bumm,6000.0)
      IrrKlangSoundSetMinDistance(*bumm,2000.0)
      IrrKlangSoundSetIsPaused(*bumm,#False)
      Debug("*explo_sound="+Str(*explo_sound))
      Debug("*bumm="+Str(*bumm))
      ;     IrrKLangPlay2D(*explo_sound)
      If stones(i)\sound
        IrrKlangSoundStop (stones(i)\sound)
      EndIf
      CompilerEndIf
      
      IrrGetNodePosition(*camera,@x.f,@y.f,@z.f)
      IrrSetNodePosition(*camera,x+0.05,y+3,z-0.05)
    Else
      
      CompilerIf #SOUND 
      If stones(i)\sound
        IrrKlangSoundSetPosition (stones(i)\sound,x,y,z)
      EndIf
      CompilerEndIf
      
      
      
    EndIf
    
    ;
    ;
    ; 		pos = SceneManager->getSceneCollisionManager()->getCollisionResultPosition(
    ; 				World, LastPosition-Translation,
    ; 				Radius, vel, triangle, f, SlidingSpeed, g);
  Next
  
  
  
  
  
  
EndProcedure


Procedure doExplosion(x.f, y.f, z.f )
  Shared *FireTexture
  Shared *Smoke2Texture
  
  
   
  ; now a little smoky...
  *ParticlesNode = IrrAddParticleSystemExtToScene( #IRR_NO_EMITTER )
  IrrSetNodePosition(*ParticlesNode,x,y,z)
  IrrSetNodeScale(*ParticlesNode, 20,20,20)
  ;  IrrSetNodePosition(*ParticlesNode,0,0,60)
  ;
  IrrSetParticleSize(*ParticlesNode,160,160)
  
  Define SmokeEmitter.IRR_PARTICLE_EMITTER
  
  With SmokeEmitter
    \min_box_x = -15
    \min_box_y = -10
    \min_box_z = -13
    \max_box_x = 13
    \max_box_y = 10
    \max_box_z = 14
    
    \direction_x = 0.0
    \direction_y = 0.0
    \direction_z = 0.0
    \min_paritlcles_per_second = 40
    \max_paritlcles_per_second = 40
    \min_start_color_red = 255
    \min_start_color_green = 255
    \min_start_color_blue = 255
    \max_start_color_red = 255
    \max_start_color_green = 255
    \max_start_color_blue = 255
    \min_lifetime = 800
    \max_lifetime = 1200
    \max_angle_degrees = 180
  EndWith
  
  *em = IrrCreateParticleEmitter(*ParticlesNode, @SmokeEmitter)
  
  ;    *em2 = IrrCreateEmitterManager(*em, 1,2, -200.0, 200.0, 1.5, 2.0, 1.0, 4.0,200, -20, 20)
  
  IrrPSExtSetInitalDelay(*ParticlesNode,200)
  IrrPSExtSetScaleRange(*ParticlesNode,0.5,2.0)
  IrrPSExtSetRotationRange(*ParticlesNode,0,360)
  IrrPSExtSetRotationSpeedRange(*ParticlesNode,-200.0, 200.0)
  IrrPSExtSetWeightRange(*ParticlesNode,1.0,4.0)
  IrrPSExtSetEmitterDelayTimes(*ParticlesNode,1,2)
  
  IrrSetParticleEmitter(*ParticlesNode,  *em)
  
  
  
  
  IrrAddGravityParticleAffector(*ParticlesNode, 0,0.05,00.0,10)
  IrrAddFadeOutParticleAffector(*ParticlesNode )
  
  IrrSetNodeMaterialFlag( *ParticlesNode, #IRR_EMF_ZBUFFER, #False)
  IrrSetNodeMaterialFlag( *ParticlesNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_ADD_COLOR  ) ; uncomment me... ;)
  IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_ALPHA_CHANNEL  ) ; uncomment me... ;)
  IrrSetNodeMaterialTexture( *ParticlesNode, *Smoke2Texture, 0 )
  IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_VERTEX_ALPHA  ) ; uncomment me... ;)
  
  IrrAddAttractionParticleAffector(*ParticlesNode , 0,0,0, 200.0, #False, #True, #True, #True)
  
  IrrAddSpinParticleAffector(*ParticlesNode, 2)
  IrrAddStopParticleAffector(*ParticlesNode, 50+300)
  IrrAddDeleteAnimator(*ParticlesNode, 5000)
  
  
  
  *ParticlesNode = IrrAddParticleSystemExtToScene( #IRR_NO_EMITTER )
  IrrSetNodePosition(*ParticlesNode,x,y,z)
  
  IrrSetNodeScale(*ParticlesNode, 1,1,1)
  
  IrrSetParticleSize(*ParticlesNode,200,200)
  
  Define ExplosionEmitter.IRR_PARTICLE_EMITTER
  
  With ExplosionEmitter
    \min_box_x = -20
    \min_box_y = -20
    \min_box_z = -10
    \max_box_x = 20
    \max_box_y = 20
    \max_box_z = 20
    
    \direction_x = 0.03
    \direction_y = 0.0
    \direction_z = 0.01
    \min_paritlcles_per_second = 30
    \max_paritlcles_per_second = 43
    \min_start_color_red = 255
    \min_start_color_green = 255
    \min_start_color_blue = 255
    \max_start_color_red = 80
    \max_start_color_green = 4
    \max_start_color_blue = 6
    \min_lifetime = 500
    \max_lifetime = 500
    \max_angle_degrees = 360
  EndWith
  
  *em = IrrCreateParticleEmitter(*ParticlesNode, @ExplosionEmitter)
  
  ;    *em2 = IrrCreateEmitterManager(*em3, 1,10, -200.0, 200.0, 1.5, 2.0, 1.0, 4.0,0, -20, 20)
  
  IrrPSExtSetInitalDelay(*ParticlesNode,0)
  IrrPSExtSetScaleRange(*ParticlesNode,1.5,2.0)
  IrrPSExtSetRotationRange(*ParticlesNode,0,360)
  IrrPSExtSetRotationSpeedRange(*ParticlesNode,-20.0, 20.0)
  IrrPSExtSetWeightRange(*ParticlesNode,1.0,4.0)
  IrrPSExtSetEmitterDelayTimes(*ParticlesNode,1,2)
  
  IrrSetParticleEmitter(*ParticlesNode,  *em)
  
  
  
  IrrAddGravityParticleAffector(*ParticlesNode, 0,0,0,1000)
  IrrAddSpinParticleAffector(*ParticlesNode, 800)
  IrrAddFadeOutParticleAffector(*ParticlesNode )
  IrrAddAttractionParticleAffector(*ParticlesNode , 0,0,0, 200.0, #False, #True, #True, #True)
  
  IrrSetNodeMaterialFlag( *ParticlesNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_ADD_COLOR  ) ; uncomment me... ;)
  IrrSetNodeMaterialFlag( *ParticlesNode, #IRR_EMF_ZBUFFER, #False)
  IrrSetNodeMaterialTexture( *ParticlesNode, *FireTexture, 0 )
  IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_VERTEX_ALPHA  ) ; uncomment me... ;)
  
  
  IrrAddStopParticleAffector(*ParticlesNode, 300)
  IrrAddDeleteAnimator(*ParticlesNode, 3000)
  ;
  ;     ;bigger ones
  ;     *ParticlesNode = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  ;     IrrSetNodeScale(*ParticlesNode, 1,1,1)
  ;     IrrSetParticleSize(*ParticlesNode,120,100)
  ;     *em = IrrAddParticleEmitter(*ParticlesNode, @CrashEmitter)
  ;
  ;     IrrAddGravityParticleAffector(*ParticlesNode, 0,-1.2,0,1000)
  ;     IrrSetNodeMaterialFlag( *ParticlesNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  ;     IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_ALPHA_CHANNEL  ) ; uncomment me... ;)
  ;     *ParticleTexture = IrrGetTexture( "..\media\Particle-011x.png" )
  ;     IrrSetNodeMaterialTexture( *ParticlesNode, *ParticleTexture, 0 )
  ;
  ;     IrrAddCollisionParticleAffector(*ParticlesNode, 0,0.0,0, 0,1,0)
  ;
  ;     IrrAddStopParticleAffector(*ParticlesNode, 300)
  ;     IrrAddDeleteAnimator(*ParticlesNode, 3000)
  ;
  ;ProcedureReturn
  
  
  
  
  
  
  
EndProcedure



ProcedureCDLL.l FSCallback(*name, read_file.l, *efs.sExternFS)
  
  Define tname.s , mem.l, i, id.l
  
  ;  Debug(PeekS(*name))
  
  ; Get the Name of the File as IrrlichtRequest it. 
  tname.s = PeekS(*name)
  
  ; Check if it starts with "myfs\", to see if it is one of
  ; our files. This is here only for example. You have not to
  ; do the same, but if Irrlicht find the file in filesystem (that
  ; is checked before) it will load from FileSystem. 
  If Left (tname, 5) = "myfs\" 
    tname = GetFilePart(tname) 
    
    Debug("search FS="+tname)
    
    pack\key = #PASS
    If OpenFilePack("media\TerrainAndParticle.pck",0,#Null)      
      id = FindPackFile(tname,0)
      Debug("id="+Str(id))
      
      If read_file  = #True
        If id <> -1 
          If (*efs <> #Null)
            *efs\memory = ExtractPackFileToMem(id) 
            *efs\len = MemorySize(*efs\memory)

            ProcedureReturn #True                  
          EndIf        
        EndIf
        ProcedureReturn #False               
      EndIf
      ProcedureReturn id
    Else
      Debug("Could not open Pack")
    EndIf
  EndIf
  
  ProcedureReturn -1
  
EndProcedure


; DataSection
; 
; heightmap_start:
; IncludeBinary ".\media\heightmap-32.raw"
; heightmap_end:
; 
; EndDataSection

; IDE Options = PureBasic 4.10 Beta 3 (Windows - x86)
; ExecutableFormat = Console
; CursorPosition = 568
; FirstLine = 538
; Folding = -
; EnableThread
; Executable = F:\Meteors\Meteors.exe
; jaPBe Version=3.7.10.668
; Build=4
; Language=0x0000 Language Neutral
; FirstLine=25
; CursorPosition=45
; ExecutableFormat=Console
; Executable=T:\projects\IrrlichtWrapperSVN\IrrlichtWrapper_1_06\PureBasic\Examples\IrrlichtWrapper\TerrainAndParticle.exe
; DontSaveDeclare
; EOF