randomize timer()
sync on
`sync rate 100
autocam off
hide mouse
 
REM INCLUDE THIS AT START OF YOUR PROGRAM
REM internal matrix data used by matrix functions
type matriks
   ix as integer
   iy as integer
   xsegs as integer
   zsegs as integer
   width as float
   depth as float
   mem_numb as integer
   obj as integer
   image as integer
   mesh as integer
   prepared as boolean
   x as float
   y as float
   z as float
   cull as integer
   light as integer
   specular as integer
endtype
 
REM INCLUDE THIS AT START OF YOUR PROGRAM
REM dim array size by maximum number of matrices you'll have
dim matrix(1) as matriks
mx = 128
mz = 128
sizex# = 4000
sizez# = 4000
REM must be called before you can create a matrix
prepare_matrix_data(1,1,1,1)
REM Make a new matrix
create_matrix(1,sizex#, sizez#,mx,mz)
REM prepare a texture for use with the matrix
`prepare_matrix_texture(1,1,1,1)
 
`load image "heightmap_01.bmp", 2
 
`set_matrix_from_heightmap(1,2,800.0)
 
`set_matrix_from_colormap(1,3)
 
randomize_matrix_faultformation(1, 15, 60, 40)
`randomize_matrix(1,200)
 
smooth_matrix(1,5)
 
`set_matrix_from_alphamap(1,4)
 
configure_matrix_normals(1)
 
set_matrix_light(1,1)
 
`set_matrix_specular(1,1)
 
`scale_matrix_texture(1,4,4)
 
REM update the matrix
update_matrix(1)
 
`set alpha mapping on 1, 100
 
 
set camera range 1, 65000
 
 
DO
 
 
 
   gosub camera_stuff
 
 
   text 2,2,str$(screen fps())
 
   if spacekey() and flag=0
      flag = 1
      if file exist("heightmap_01.bmp") then delete file "heightmap_01.bmp"
      save_heightmap(50, "heightmap_01.bmp", 1)
      `texture object 5,50
   endif
 
   if spacekey()=0 then flag=0
 
 
 
 
   sync
LOOP
 
 
REM ==========================================================================
REM Parameters:
REM image number
REM file name to save as
REM matrix number
function save_heightmap(img as integer, filename as string, mat as integer)
   highpt# = 0
   lowpt# = 0
   for x=0 to matrix(mat).xsegs
      for z=0 to matrix(mat).zsegs
         h# = get_matrix_height(mat,x,z)
         if h# > highpt# then highpt# = h#
         if h# < lowpt# then lowpt# = h#
      next z
   next x
 
   lowpt# = abs(lowpt#)
 
   mem = 200
   width = matrix(mat).xsegs+1
   height = matrix(mat).zsegs+1
   size = width*height*4 + 12
   make memblock mem, size
   write memblock dword mem, 0, width
   write memblock dword mem, 4, height
   write memblock dword mem, 8, 32
 
   for x=0 to matrix(mat).xsegs
      for z=0 to matrix(mat).zsegs
         h# = get_matrix_height(mat,x,z) + lowpt#
         color = (h# * 255) / highpt#
         location = (z*width + x)*4 + 12
         write memblock dword mem, location, rgb(color, color, color)
      next z
   next x
 
   make image from memblock img, mem
   save image filename, img
 
   delete memblock mem
 
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM object used to create matrix
REM memblock number used to create matrix
REM mesh number used to create object from memblock
function prepare_matrix_data(number as integer, object as integer, mb as integer, mesh as integer)
   matrix(number).obj = object
   matrix(number).mem_numb = mb
   matrix(number).mesh = mesh
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM number of image tiles across
REM number of image tiles down
function scale_matrix_texture(number as integer, across as integer, down as integer)
   matrix(number).ix = across
   matrix(number).iy = down
   matrix(number).prepared = 1
 
   tile = 1
   ln = 0
   for z = matrix(number).zsegs to 1 step -1
      for x = 1 to matrix(number).xsegs
         tl = ln*across + tile
         set_matrix_tile(number, x, z, tl)
         inc tile, 1
         if tile > across then tile = 1
      next x
      inc ln, 1
      if ln > down-1 then ln = 0
   next z
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM image number
REM number of image tiles across
REM number of image tiles down
function prepare_matrix_texture(number as integer, image as integer, across as integer, down as integer)
   matrix(number).ix = across
   matrix(number).iy = down
   matrix(number).image = image
   matrix(number).prepared = 1
   `texture object matrix(number).obj, matrix(number).image
 
   for z = 1 to matrix(number).zsegs
      for x = 1 to matrix(number).xsegs
         set_matrix_tile(number, x, z, 1)
      next x
   next z
 
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM width of matrix
REM depth of matrix
REM number of X segments
REM number of Z segments
function create_matrix(number as integer, width as float, depth as float, xsegs as integer, zsegs as integer)
   fvf = 338
   size = 36
   matrix(number).width = width
   matrix(number).depth = depth
   matrix(number).xsegs = xsegs
   matrix(number).zsegs = zsegs
   numb_verts = matrix(number).xsegs * matrix(number).zsegs * 6
   total_size = numb_verts*size + 12
   tile_size_x# = width/matrix(number).xsegs
   tile_size_z# = depth/matrix(number).zsegs
   mem_numb = matrix(number).mem_numb
 
   make memblock mem_numb, total_size
   write memblock dword mem_numb, 0, fvf
   write memblock dword mem_numb, 4, size
   write memblock dword mem_numb, 8, numb_verts
 
   tile = 0
   for z = 1 to zsegs
      for x = 1 to xsegs
         location = tile*size*6 + 12
 
         x1# = tile_size_x# * (x-1)
         y1# = 0
         z1# = tile_size_z# * (z-1)
 
         x2# = tile_size_x# * (x-1)
         y2# = 0
         z2# = tile_size_z# * z
 
         x3# = tile_size_x# * x
         y3# = 0
         z3# = tile_size_z# * z
 
         x4# = x1#
         y4# = y1#
         z4# = z1#
 
         x5# = x3#
         y5# = y3#
         z5# = z3#
 
         x6# = x3#
         y6# = 0
         z6# = z1#
 
         rem vert 1 - x,y,z, normals x,y,z, diffuse color
         write memblock float mem_numb, location, x1#
         write memblock float mem_numb, location+4, y1#
         write memblock float mem_numb, location+8, z1#
         write memblock float mem_numb, location+12, 0
         write memblock float mem_numb, location+16, 1
         write memblock float mem_numb, location+20, 0
         write memblock dword mem_numb, location+24, rgb(255,255,255)
 
         rem vert 2 - x,y,z
         temp_size = size
         write memblock float mem_numb, location+temp_size, x2#
         write memblock float mem_numb, location+temp_size+4, y2#
         write memblock float mem_numb, location+temp_size+8, z2#
         write memblock float mem_numb, location+temp_size+12, 0
         write memblock float mem_numb, location+temp_size+16, 1
         write memblock float mem_numb, location+temp_size+20, 0
         write memblock dword mem_numb, location+temp_size+24, rgb(255,255,255)
 
         rem vert 3 - x,y,z
         temp_size = size*2
         write memblock float mem_numb, location+temp_size, x3#
         write memblock float mem_numb, location+temp_size+4, y3#
         write memblock float mem_numb, location+temp_size+8, z3#
         write memblock float mem_numb, location+temp_size+12, 0
         write memblock float mem_numb, location+temp_size+16, 1
         write memblock float mem_numb, location+temp_size+20, 0
         write memblock dword mem_numb, location+temp_size+24, rgb(255,255,255)
 
         rem vert 4 - x,y,z
         temp_size = size*3
         write memblock float mem_numb, location+temp_size, x4#
         write memblock float mem_numb, location+temp_size+4, y4#
         write memblock float mem_numb, location+temp_size+8, z4#
         write memblock float mem_numb, location+temp_size+12, 0
         write memblock float mem_numb, location+temp_size+16, 1
         write memblock float mem_numb, location+temp_size+20, 0
         write memblock dword mem_numb, location+temp_size+24, rgb(255,255,255)
 
         rem vert 5 - x,y,z
         temp_size = size*4
         write memblock float mem_numb, location+temp_size, x5#
         write memblock float mem_numb, location+temp_size+4, y5#
         write memblock float mem_numb, location+temp_size+8, z5#
         write memblock float mem_numb, location+temp_size+12, 0
         write memblock float mem_numb, location+temp_size+16, 1
         write memblock float mem_numb, location+temp_size+20, 0
         write memblock dword mem_numb, location+temp_size+24, rgb(255,255,255)
 
         rem vert 6 - x,y,z
         temp_size = size*5
         write memblock float mem_numb, location+temp_size, x6#
         write memblock float mem_numb, location+temp_size+4, y6#
         write memblock float mem_numb, location+temp_size+8, z6#
         write memblock float mem_numb, location+temp_size+12, 0
         write memblock float mem_numb, location+temp_size+16, 1
         write memblock float mem_numb, location+temp_size+20, 0
         write memblock dword mem_numb, location+temp_size+24, rgb(255,255,255)
 
         inc tile, 1
 
      next x
   next z
 
   make mesh from memblock  1, mem_numb
   make object matrix(number).obj,1,0
 
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM tile X (grid-based coordinate)
REM tile Z (grid-based coordinate)
REM tile is an image tile number (from prepare_matrix_texture())
function set_matrix_tile(number as integer, tileX as integer, tileZ as integer, tile as integer)
 
   if tileX < 0 OR tileX > matrix(number).xsegs OR tileX < 0 OR tileZ > matrix(number).zsegs OR matrix(number).prepared = 0
      exitfunction
   endif
 
   if matrix(number).ix = 0 then matrix(number).ix = 1
   if matrix(number).iy = 0 then matrix(number).iy = 1
 
 
   mem_numb = matrix(number).mem_numb
   size = 36
   boffset = size*6
 
   location = 12 + ((tileZ-1)*matrix(number).xsegs*boffset + (tileX-1)*boffset)
 
   x_temp = wrap(tile, matrix(number).ix)
 
   mix# = matrix(number).ix
   x_max# = x_temp/mix#
   x_min# = (x_temp-1)/mix#
 
   y_temp = int((tile - x_temp) / mix#) + 1.0
 
   miy# = matrix(number).iy
   y_max# = y_temp/miy#
   y_min# = (y_temp-1)/miy#
 
 
   if y_min# > 0 then y_min# = y_min# + 0.01
   if x_min# > 0 then x_min# = x_min# + 0.01
 
 
   rem vert 1 - UV coordinates
   write memblock float mem_numb, location+28, x_min#
   write memblock float mem_numb, location+32, y_max#
 
   rem vert 2
   write memblock float mem_numb, location+64, x_min#
   write memblock float mem_numb, location+68, y_min#
 
   rem vert 3
   write memblock float mem_numb, location+100, x_max#
   write memblock float mem_numb, location+104, y_min#
 
   rem vert 4
   write memblock float mem_numb, location+136, x_min#
   write memblock float mem_numb, location+140, y_max#
 
   rem vert 5
   write memblock float mem_numb, location+172, x_max#
   write memblock float mem_numb, location+176, y_min#
 
   rem vert 6
   write memblock float mem_numb, location+208, x_max#
   write memblock float mem_numb, location+212, y_max#
 
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM tile X (grid-based coordinate)
REM tile Z (grid-based coordinate)
REM diffuse color
 
function set_matrix_diffuse(number as integer, tile_x as integer, tile_z as integer, color as dword)
 
   if tile_x < 0 OR tile_x > matrix(number).xsegs OR tile_z < 0 OR tile_z > matrix(number).zsegs
      exitfunction
   endif
   size = 36
   boffset = size*6
   numb_verts = matrix(number).xsegs * matrix(number).zsegs * 6
   total_size = numb_verts*size + 12
   tile_size_x# = width/matrix(number).xsegs
   tile_size_z# = height/matrix(number).zsegs
   mem_numb = matrix(number).mem_numb
   lensize = matrix(number).xsegs*boffset
 
   REM verts 3 and 5
   if tile_x > 0 and tile_z > 0
      gx = tile_x - 1
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock dword mem_numb, location+96, color
      write memblock dword mem_numb, location+168, color
   endif
 
   REM vert 2
   if tile_z > 0 and tile_x < matrix(number).xsegs
      gx = tile_x
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock dword mem_numb, location+60, color
   endif
 
   rem vert 6
   if tile_x > 0 and tile_z < matrix(number).zsegs
     gx = tile_x - 1
     gz = tile_z
     location = gz*lensize + gx*boffset + 12
     write memblock dword mem_numb, location+204, color
   endif
 
   rem verts 1 and 4
   if tile_x < matrix(number).xsegs and tile_z < matrix(number).zsegs
      gx = tile_x
      gz = tile_z
      location = gz*lensize + gx*boffset + 12
      write memblock dword mem_numb, location+24, color
      write memblock dword mem_numb, location+132, color
   endif
 
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM tile X (grid-based coordinate)
REM tile Z (grid-based coordinate)
REM alpha value
function set_matrix_alpha(number as integer, tile_x as integer, tile_z as integer, alpha as integer)
 
   if tile_x < 0 OR tile_x > matrix(number).xsegs OR tile_z < 0 OR tile_z > matrix(number).zsegs
      exitfunction
   endif
   size = 36
   boffset = size*6
   numb_verts = matrix(number).xsegs * matrix(number).zsegs * 6
   total_size = numb_verts*size + 12
   tile_size_x# = width/matrix(number).xsegs
   tile_size_z# = height/matrix(number).zsegs
   mem_numb = matrix(number).mem_numb
   lensize = matrix(number).xsegs*boffset
 
   REM verts 3 and 5
   if tile_x > 0 and tile_z > 0
      gx = tile_x - 1
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock dword mem_numb, location+99, alpha
      write memblock dword mem_numb, location+171, alpha
   endif
 
   REM vert 2
   if tile_z > 0 and tile_x < matrix(number).xsegs
      gx = tile_x
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock dword mem_numb, location+63, alpha
   endif
 
   rem vert 6
   if tile_x > 0 and tile_z < matrix(number).zsegs
     gx = tile_x - 1
     gz = tile_z
     location = gz*lensize + gx*boffset + 12
     write memblock dword mem_numb, location+207, alpha
   endif
 
   rem verts 1 and 4
   if tile_x < matrix(number).xsegs and tile_z < matrix(number).zsegs
      gx = tile_x
      gz = tile_z
      location = gz*lensize + gx*boffset + 12
      write memblock dword mem_numb, location+27, alpha
      write memblock dword mem_numb, location+135, alpha
   endif
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM tile X (grid-based coordinate)
REM tile Z (grid-based coordinate)
REM height (height of tile you're setting)
 
function set_matrix_height(number as integer, tile_x as integer, tile_z as integer, height# as float)
 
   if tile_x < 0 OR tile_x > matrix(number).xsegs OR tile_z < 0 OR tile_z > matrix(number).zsegs
      exitfunction
   endif
 
   size = 36
   boffset = size*6
   numb_verts = matrix(number).xsegs * matrix(number).zsegs * 6
   total_size = numb_verts*size + 12
   tile_size_x# = width/matrix(number).xsegs
   tile_size_z# = height/matrix(number).zsegs
   mem_numb = matrix(number).mem_numb
   lensize = matrix(number).xsegs*boffset
 
   REM verts 3 and 5
   if tile_x > 0 and tile_z > 0
      gx = tile_x - 1
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+76, height#
      write memblock float mem_numb, location+148, height#
   endif
 
   REM vert 2
   if tile_z > 0 and tile_x < matrix(number).xsegs
      gx = tile_x
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+40, height#
   endif
 
   rem vert 6
   if tile_x > 0 and tile_z < matrix(number).zsegs
   `and tile_z < matrix(number).zsegs
     gx = tile_x - 1
     gz = tile_z
     location = gz*lensize + gx*boffset + 12
     write memblock float mem_numb, location+184, height#
   endif
 
   rem verts 1 and 4
   if tile_x < matrix(number).xsegs and tile_z < matrix(number).zsegs
      gx = tile_x
      gz = tile_z
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+4, height#
      write memblock float mem_numb, location+112, height#
   endif
 
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM tile X (grid-based coordinate)
REM tile Z (grid-based coordinate)
REM nx,ny,nz - normal
function set_matrix_normal(number as integer, tile_x as integer, tile_z as integer, nx as float, ny as float, nz as float)
 
   if tile_x < 0 OR tile_x > matrix(number).xsegs OR tile_z < 0 OR tile_z > matrix(number).zsegs
      exitfunction
   endif
   size = 36
   boffset = size*6
   numb_verts = matrix(number).xsegs * matrix(number).zsegs * 6
   total_size = numb_verts*size + 12
   tile_size_x# = width/matrix(number).xsegs
   tile_size_z# = height/matrix(number).zsegs
   mem_numb = matrix(number).mem_numb
   lensize = matrix(number).xsegs*boffset
 
   REM verts 3 and 5
   if tile_x > 0 and tile_z > 0
      gx = tile_x - 1
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+84, nx
      write memblock float mem_numb, location+88, ny
      write memblock float mem_numb, location+92, nz
 
      write memblock float mem_numb, location+156, nx
      write memblock float mem_numb, location+160, ny
      write memblock float mem_numb, location+164, nz
   endif
 
   REM vert 2
   if tile_z > 0 and tile_x < matrix(number).xsegs
      gx = tile_x
      gz = tile_z - 1
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+48, nx
      write memblock float mem_numb, location+52, ny
      write memblock float mem_numb, location+56, nz
   endif
 
   rem vert 6
   if tile_x > 0 and tile_z < matrix(number).zsegs
      gx = tile_x - 1
      gz = tile_z
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+192, nx
      write memblock float mem_numb, location+196, ny
      write memblock float mem_numb, location+200, nz
   endif
 
   rem verts 1 and 4
   if tile_x < matrix(number).xsegs and tile_z < matrix(number).zsegs
      gx = tile_x
      gz = tile_z
      location = gz*lensize + gx*boffset + 12
      write memblock float mem_numb, location+12, nx
      write memblock float mem_numb, location+16, ny
      write memblock float mem_numb, location+20, nz
 
      write memblock float mem_numb, location+120, nx
      write memblock float mem_numb, location+124, ny
      write memblock float mem_numb, location+128, nz
   endif
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM X coordinate
REM Z coordinate
function get_ground_height(number as integer, x#, z#)
 
  `h# = intersect object(matrix(number).obj,x#,0,z#,x#,10000,z#)
  `exitfunction h#
 
  tileSizeX# = matrix(number).width / matrix(number).xsegs
  tileSizeZ# = matrix(number).depth / matrix(number).zsegs
 
  row = z# / tileSizeZ#
  column = x# / tileSizeX#
 
  if row < 0 OR row >= matrix(number).xsegs OR column < 0 or column >= matrix(number).zsegs
      exitfunction 0.0
  endif
 
  tile=row*matrix(number).xsegs+column
  znorm#=z#-row*tileSizeZ#
  xnorm#=x#-column*tileSizeX#
 
  rem get the right triangle
  if tileSizeZ#*xnorm#>=tileSizeX#*znorm#
    location=12+tile*216+112
    y1#=memblock float(matrix(number).mem_numb,location)
    y2#=memblock float(matrix(number).mem_numb,location+36)
    y3#=memblock float(matrix(number).mem_numb,location+72)
    y#=y1#+(znorm#/tileSizeZ#)*(y2#-y3#)+(xnorm#/tileSizeX#)*(y3#-y1#)
  else
    location=12+tile*216+4
    y1#=memblock float(matrix(number).mem_numb,location)
    y2#=memblock float(matrix(number).mem_numb,location+36)
    y3#=memblock float(matrix(number).mem_numb,location+72)
    y#=y1#+(znorm#/tileSizeZ#)*(y2#-y1#)+(xnorm#/tileSizeX#)*(y3#-y2#)
  endif
 
endfunction y#
 
 
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM tile X (grid-based coordinate)
REM tile Z (grid-based coordinate)
function get_matrix_height(number as integer, tile_x as integer, tile_z as integer)
   if tile_x < 0 OR tile_x > matrix(number).xsegs OR tile_z < 0 OR tile_z > matrix(number).zsegs
      exitfunction
   endif
 
   size = 36
   boffset = size*6
   numb_verts = matrix(number).xsegs * matrix(number).zsegs * 6
   total_size = numb_verts*size + 12
   tile_size_x# = width/matrix(number).xsegs
   tile_size_z# = height/matrix(number).zsegs
   mem_numb = matrix(number).mem_numb
   lensize = matrix(number).xsegs*boffset
 
   if tile_x < matrix(number).xsegs and tile_z < matrix(number).zsegs
      location = tile_z*lensize + tile_x*boffset + 12
      yheight# = memblock float (mem_numb, location+4)
   else
      if tile_x = matrix(number).xsegs
         if tile_z = matrix(number).zsegs
            location = (tile_z-1)*lensize + (tile_x-1)*boffset + 12
            yheight# = memblock float (mem_numb, location+76)
         else
            location = (tile_z)*lensize + (tile_x-1)*boffset + 12
            yheight# = memblock float (mem_numb, location+184)
         endif
      else
         location = (tile_z-1)*lensize + (tile_x)*boffset + 12
         yheight# = memblock float (mem_numb, location+40)
      endif
   endif
 
endfunction yheight#
 
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM image number
REM maximum height
function set_matrix_from_heightmap(number as integer, img as integer, max as float)
   make memblock from image 256, img
   width# = memblock dword(256, 0)
   height# = memblock dword(256, 4)
 
   ox# = width#/(matrix(number).xsegs+1)
   oz# = height#/(matrix(number).zsegs+1)
 
   for z = 0 to matrix(number).zsegs
      for x = 0 to matrix(number).xsegs
         location = (int(z*oz#)*width# + int(x*ox#))*4 + 12
         c = memblock byte(256, location)
         rem convert color value into height value
         h# = (c*max)/255.0
         set_matrix_height(number,x,z,h#)
      next x
   next z
 
   delete memblock 256
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM image number
function set_matrix_from_colormap(number as integer, img as integer)
   make memblock from image 256, img
   width# = memblock dword(256, 0)
   height# = memblock dword(256, 4)
 
   ox# = width#/(matrix(number).xsegs+1)
   oz# = height#/(matrix(number).zsegs+1)
 
   for z = 0 to matrix(number).zsegs
      for x = 0 to matrix(number).xsegs
         location = (int(z*oz#)*width# + int(x*ox#))*4 + 12
         b = memblock byte(256, location)
         g = memblock byte(256, location+1)
         r = memblock byte(256, location+2)
         c = rgb(r,g,b)
         set_matrix_diffuse(number,x,z,c)
      next x
   next z
 
   delete memblock 256
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM image number
function set_matrix_from_alphamap(number as integer, img as integer)
   make memblock from image 256, img
   width# = memblock dword(256, 0)
   height# = memblock dword(256, 4)
 
   ox# = width#/(matrix(number).xsegs+1)
   oz# = height#/(matrix(number).zsegs+1)
 
   for z = 0 to matrix(number).zsegs
      for x = 0 to matrix(number).xsegs
         location = (int(z*oz#)*width# + int(x*ox#))*4 + 12
         a = memblock byte(256, location+3)
         set_matrix_alpha(number,x,z,a)
      next x
   next z
 
   delete memblock 256
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM X,Y,Z coordinates
function position_matrix(number as integer, x as float, y as float, z as float)
   matrix(number).x = x
   matrix(number).y = y
   matrix(number).z = z
   position object matrix(number).obj, x, y, z
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
function update_matrix(number as integer)
   change mesh from memblock matrix(number).mesh, matrix(number).mem_numb
   delete object matrix(number).obj
   make object matrix(number).obj, matrix(number).mesh, matrix(number).image
   set object cull matrix(number).obj, matrix(number).cull
   set object light matrix(number).obj, matrix(number).light
   set object specular matrix(number).obj, matrix(number).specular
   position object matrix(number).obj, matrix(number).x, matrix(number).y, matrix(number).z
   if matrix(number).prepared = 0
      set object wireframe matrix(number).obj, 1
   endif
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM flag, on or off
function set_matrix_cull(number as integer, flag as integer)
   matrix(number).cull = flag
   set object cull matrix(number).obj, flag
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM flag, on or off
function set_matrix_light(number as integer, flag as integer)
   matrix(number).light = flag
   set object light matrix(number).obj, flag
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM flag, on or off
function set_matrix_specular(number as integer, flag as integer)
   matrix(number).specular = flag
   set object specular matrix(number).obj, flag
endfunction
 
 
 
remstart
REM ==========================================================================
REM Coded by Dr. DB himself, Lee Bamber
REM Parameters:
REM matrix number
function configure_matrix_normals(number as integer)
   for z=1 to matrix(number).zsegs-1
      for x=1 to matrix(number).xsegs-1
 
         rem Get matrix heights
         h8#=get_matrix_height(number,x,z-1)
         h4#=get_matrix_height(number,x-1,z)
         h#=get_matrix_height(number,x,z)
         h2#=get_matrix_height(number,x,z)
 
         rem Calculate projected angle X using heights
         x1#=(x-1)*25.0 : y1#=h#
         x2#=(x+0)*25.0 : y2#=h4#
         dx#=x2#-x1#
         dy#=y2#-y1#
         ax#=atanfull(dx#,dy#)
         ax#=wrapvalue(90-ax#)
 
         rem Calculate projected angle Z using heights
         z1#=(z-1)*25.0 : y1#=h2#
         z2#=(z+0)*25.0 : y2#=h8#
         dz#=z2#-z1#
         dy#=y2#-y1#
         az#=atanfull(dz#,dy#)
         az#=wrapvalue(90-az#)
 
         rem Make normal from projected angle
         nx#=sin(ax#)
         ny#=cos(ax#)
         nz#=sin(az#)
 
         rem Setting matrix normal for smoothness
         set_matrix_normal(number,x,z,nx#,ny#,nz#)
      next x
   next z
endfunction
remend
 
 
 
function configure_matrix_normals(number as integer)
   size = 36
   boffset = size*6
   mem = matrix(number).mem_numb
   lensize = matrix(number).xsegs*boffset
 
   p1 = 1
   p2 = 2
   p3 = 3
   p4 = 4
   p5 = 5
   p6 = 6
   av1 = 7
   bv1 = 8
   av2 = 9
   bv2 = 10
   n1 = 11
   n2 = 12
 
   null = make vector3(p1)
   null = make vector3(p2)
   null = make vector3(p3)
   null = make vector3(p4)
   null = make vector3(p5)
   null = make vector3(p6)
   null = make vector3(av1)
   null = make vector3(bv1)
   null = make vector3(av2)
   null = make vector3(bv2)
   null = make vector3(n1)
   null = make vector3(n2)
 
 
   for z=0 to matrix(number).zsegs-1
      for x=0 to matrix(number).xsegs-1
         location = z*lensize + x*boffset + 12
         set vector3 p1,memblock float(mem,location),memblock float(mem,location+4),memblock float(mem,location+8)
         set vector3 p2,memblock float(mem,location+36),memblock float(mem,location+40),memblock float(mem,location+44)
         set vector3 p3,memblock float(mem,location+72),memblock float(mem,location+76),memblock float(mem,location+80)
         set vector3 p4,memblock float(mem,location+108),memblock float(mem,location+112),memblock float(mem,location+116)
         set vector3 p5,memblock float(mem,location+144),memblock float(mem,location+148),memblock float(mem,location+152)
         set vector3 p6,memblock float(mem,location+180),memblock float(mem,location+184),memblock float(mem,location+188)
 
         subtract vector3 av1,p2,p1
         subtract vector3 bv1,p3,p2
         subtract vector3 av2,p5,p4
         subtract vector3 bv2,p6,p5
 
         cross product vector3 n1,av1,bv1
         cross product vector3 n2,av2,bv2
 
         normalize vector3 n1,n1
         normalize vector3 n2,n2
 
         rem vert 1
         write memblock float mem, location+12, x vector3(n1)
         write memblock float mem, location+16, y vector3(n1)
         write memblock float mem, location+20, z vector3(n1)
         rem vert 2
         write memblock float mem, location+48, x vector3(n1)
         write memblock float mem, location+52, y vector3(n1)
         write memblock float mem, location+56, z vector3(n1)
         rem vert 3
         write memblock float mem, location+84, x vector3(n1)
         write memblock float mem, location+88, y vector3(n1)
         write memblock float mem, location+92, z vector3(n1)
         rem vert 4
         write memblock float mem, location+120, x vector3(n2)
         write memblock float mem, location+124, y vector3(n2)
         write memblock float mem, location+128, z vector3(n2)
         rem vert 5
         write memblock float mem, location+156, x vector3(n2)
         write memblock float mem, location+160, y vector3(n2)
         write memblock float mem, location+164, z vector3(n2)
         rem vert 6
         write memblock float mem, location+192, x vector3(n2)
         write memblock float mem, location+196, y vector3(n2)
         write memblock float mem, location+200, z vector3(n2)
      next x
   next z
 
endfunction
 
 
 
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM number of iterations
REM add amount
REM subtract amount
function randomize_matrix_faultformation(number as integer, iter as integer, h1# as float, h2# as float)
 
   tsx# = matrix(number).width / matrix(number).xsegs
   tsz# = matrix(number).depth / matrix(number).zsegs
   for t = 1 to iter
      rx1# = rnd(matrix(number).width)
      rz1# = rnd(matrix(number).depth)
      rx2# = rnd(matrix(number).width)
      rz2# = rnd(matrix(number).depth)
 
 
      for z = 0 to matrix(number).zsegs
         for x = 0 to matrix(number).xsegs
 
            px# = x * tsx#
            pz# = z * tsz#
 
            h# = get_matrix_height(number,x,z)
 
            if point_line(px#,pz#,rx1#,rz1#,rx2#,rz2#) >= 0
               set_matrix_height(number,x,z,h#+h1#)
            else
               set_matrix_height(number,x,z,h#-h2#)
            endif
         next x
      next z
 
   next t
 
endfunction
 
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM number of iterations
function smooth_matrix(number as integer, iter as integer)
 
   dim heights#(matrix(number).xsegs,matrix(number).zsegs)
 
 
 
   for t = 1 to iter
      rem store original heights
      for z = 0 to matrix(number).zsegs
         for x = 0 to matrix(number).xsegs
            heights#(x,z) = get_matrix_height(number,x,z)
         next x
      next z
 
      for z = 0 to matrix(number).zsegs
         for x = 0 to matrix(number).xsegs
            count = 0
            h1# = 0
            h2# = 0
            h3# = 0
            h4# = 0
            h5# = 0
            h6# = 0
            h7# = 0
            h8# = 0
 
           if z < matrix(number).zsegs
               if x > 0 then h1# = heights#(x-1,z+1) : inc count
               h2# = heights#(x,z+1) : inc count
               if x < matrix(number).xsegs then h3# = heights#(x+1,z+1) : inc count
            endif
 
            if x > 0 then h4# = heights#(x-1,z) : inc count
            if x < matrix(number).xsegs then h5# = heights#(x+1,z) : inc count
 
            if z > 0
               if x > 0 then h6# = heights#(x-1,z-1) : inc count
               h7# = heights#(x,z-1) : inc count
               if x < matrix(number).xsegs then h8# = heights#(x+1,z-1) : inc count
            endif
 
            avg# = (h1#+h2#+h3#+h4#+h5#+h6#+h7#+h8#) / count
 
            set_matrix_height(number,x,z,avg#)
 
         next x
      next z
   next t
 
   rem delete array
   undim heights#()
 
endfunction
 
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM max height
function randomize_matrix(number as integer, height as float)
   for z = 0 to matrix(number).zsegs
      for x = 0 to matrix(number).xsegs
         set_matrix_height(number, x, z, rnd(height*100.0)/100.0)
      next x
   next z
endfunction
 
 
REM ==========================================================================
REM Parameters:
REM matrix number
REM X,Y screen coordinates
REM vector number to store results in
function pick_matrix(number as integer, x as integer, y as integer, vector as integer)
   if matrix(number).obj = 0 then exitfunction
 
   t = pick object(x,y,matrix(number).obj,matrix(number).obj)
   vx# = camera position X()+get pick vector x()
   vy# = camera position y()+get pick vector y()
   vz# = camera position z()+get pick vector z()
   set vector3 vector, vx#, vy#, vz#
endfunction
 
 
REM wrapvalue function
REM Wraps n1# to n2#
function wrap(n1#,n2#)
 
   while (n1# > n2#)
      n1# = n1# - n2#
   endwhile
 
endfunction n1#
 
 
 
REM if point(px,py) is right or left of line segment (x1,y1),(x2,y2)
REM return negative if left, positive if right, 0 if on
function point_line(px#,py#, x1#,y1#,x2#,y2#)
   dp# = (x2# - x1#) * (py# - y1#) - (px# - x1#) * (y2# - y1#)
endfunction dp#
 
 
 
camera_stuff:
  oldcx#=cx#
  oldcz#=cz#
  speed# = 5
 
  if shiftkey() then speed# = 10
  if upkey()=1
    cx#=newxvalue(cx#,a#,speed#)
    cz#=newzvalue(cz#,a#,speed#)
  endif
  if downkey()=1
    cx#=newxvalue(cx#,a#,-speed#)
    cz#=newzvalue(cz#,a#,-speed#)
  endif
  if leftkey()=1
    cx#=newxvalue(cx#,wrapvalue(a#-90.0),speed#)
    cz#=newzvalue(cz#,wrapvalue(a#-90.0),speed#)
  endif
  if rightkey()=1
    cx#=newxvalue(cx#,wrapvalue(a#+90.0),speed#)
    cz#=newzvalue(cz#,wrapvalue(a#+90.0),speed#)
  endif
 
   `if shiftkey() then inc cy#, 2
   `if controlkey() then dec cy#, 2
 
  a#=wrapvalue(a#+(mousemovex()/3.0))
  cxa#=cxa#+(mousemovey()/3.0)
  if cxa#<-90.0 then cxa#=-90.0
  if cxa#>90.0 then cxa#=90.0
  cy# = get_ground_height(1,cx#,cz#)
  position camera cx#,cy#+50,cz#
  rotate camera wrapvalue(cxa#),a#,0
RETURN