Hi Daryn,are you planing on using the built in LOD commands,a dll,or coding your own.I do have a little experience with the built in commands which seem ok as long as you build your landscape models well.I tend to make one large landscape height grid in a common aray,then sub devide it into an 8 by 8 grid of objects,LOD objects use either all the points for the nearest, every second point for the mid LOD and every fourth point for the far LOD. The objects then remain the same size but with fewer polyies,just what you need for LOD.The down side is the edges dont line up well if there is a sudden shift in height from vertex to vertex but if you set up the LOD ranges right you dont get close enough to see this.
I have some code here for you to try,if you weant to see the LOD in action then scroll down to the 'global wf' and set it to 1.
read through the code first and save it into a folder before you run it as it sets up folders to save all the objects and textures for later use and change the names if you want.
It also uses EZRotate,if you dont have it then change the 'global ez' to 0 and delete the code thats in 'make_normals' function that looks like this
IF ez=1
EZRO_FINDNORMAL x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3#
xn#=EZRO_GETNORMALX()
yn#=EZRO_GETNORMALY()
zn#=EZRO_GETNORMALZ()
ENDIF
Write now for the whole code,its rather large and does a lot more then LOD but it shows the principles.
`LAND MAP LOD 2
`======================
`©Paul Parkinson
`======================
`Main Source File
`############################################################## SYSTEM SETUP
SYNC ON
SYNC RATE 60
AUTOCAM OFF
COLOR BACKDROP 0,0
SET CAMERA RANGE 1,20000`set at long range to test LOD,Routines Shorten range for speed
SET TEXT FONT "Arial"
SET TEXT SIZE 24
SET TEXT TRANSPARENT
`###################################################################### LIGHTS & CAMERA
`set up camera and lights
POSITION CAMERA -1000,3000,-1000
POINT CAMERA 3000,0,3000
MAKE LIGHT 1
SET POINT LIGHT 1,5000,5000,5000
SET LIGHT RANGE 1,50000
HIDE LIGHT 0
SET AMBIENT LIGHT 0
MAKE OBJECT SPHERE 10000,-100
COLOR OBJECT 10000,RGB(255,255,0)
TEXT 0,0,"Please Wait - Starting Up"
SYNC
SYNC
`############################################################## NORMAL CREATION
GLOBAL ez=1`change to 1 if you have ez_rotate installed to speed up the build process or 0 to use vector maths method
`remember to comment out the ez_rotate commands as well if you dont have it
`there located in the 'make_normals()' function
IF ez=0
GLOBAL avx#:GLOBAL avy#:GLOBAL avz#
null = MAKE VECTOR3(0)
null = MAKE VECTOR3(1)
null = MAKE VECTOR3(2)
null = MAKE VECTOR3(5)
null = MAKE VECTOR3(6)
null = MAKE VECTOR3(9)
null = MAKE VECTOR3(10)
ENDIF
`############################################################## SAVE DIRECTORIES
GLOBAL save=1`change this to 0 if you dont want save the dbo's and bmp's that are created
`if you do then change the folder names to suit your self
GLOBAL bmp$="bmp"`base folder to store textures in
GLOBAL dbo$="dbo"`base folder to store objects in
`make folders if not present
IF save=1
IF NOT PATH EXIST(bmp$)
MAKE DIRECTORY bmp$`this folder also holds base textures
ENDIF
IF NOT PATH EXIST(dbo$)
MAKE DIRECTORY dbo$
ENDIF
IF NOT PATH EXIST(dbo$+"lod1")
MAKE DIRECTORY dbo$+"lod1"
ENDIF
IF NOT PATH EXIST(dbo$+"lod2")
MAKE DIRECTORY dbo$+"lod2"
ENDIF
ENDIF
`############################################################## TEXTURE SETUP
`global texture variables used if *.raw data file is inported,otherwise these will be set up in the fractal routine but need initialising first
GLOBAL sand1#:sand1#=45
GLOBAL sand2#:sand2#=70
GLOBAL sand3#:sand3#=90
GLOBAL grass1#:grass1#=120
GLOBAL grass2#:grass2#=170
GLOBAL grass3#:grass3#=190
GLOBAL rock1#:rock1#=220
GLOBAL rock2#:rock2#=240
GLOBAL rock3#:rock3#=270
GLOBAL rock4#:rock4#=310
GLOBAL rock5#:rock5#=360
`############################################################## WORLD SETUP
`random variation based on this value
GLOBAL hmv#:hmv#=15.0
GLOBAL blend:blend=64
`total size of world
TEXT 0,0,"Please Wait - Building World Data"
SYNC
GLOBAL grid_x#:GLOBAL grid_z#
grid_x#=512:grid_z#=512`do not adjust
DIM map_data(grid_x#,grid_z#,8) AS FLOAT `you have to setup the main map_data array before you can build the terrain
`uv set up
GLOBAL near_lod AS FLOAT:GLOBAL mid_lod AS FLOAT :GLOBAL far_lod AS FLOAT
near_lod=64.0:mid_lod=32.0:far_lod=16.0
GLOBAL u# AS DOUBLE FLOAT:GLOBAL v# AS DOUBLE FLOAT
`grid_size# is the size of each polygon used,this will scale the whole world but only the x,z plane so the hills will be more abrupt
`make the changes in the fractal generator function to smooth this out
GLOBAL grid_size#
grid_size#=32.0
`bitmap size for texture
GLOBAL bitmap_size#
`make a random hight map or read in a data file
RANDOMIZE TIMER()
GLOBAL scale AS FLOAT
scale=2.2
`read_hmap()`reads in a 512x512 teragen raw data height map these are not tileable
hmap_fractal()`make random fractal height map these are tileable
`map_data(xpos,zpos,8) array is used like this
`(1)=height (2),(3),(4)=normal x,y,z this is the total for all the normals at that vertex (5)=number of vertex sharing that point
`devides (2),(3),(4) by (5) to get the averaged normal
`(6),(7),(8) can be used for diffuse color if needed
make_normals()
`turn on wire frame
GLOBAL wf=0`1 is on 0 is off,this will also turn off the texturing process if wire frame is selected
`#################################################################### LOD OBJECT CREATION
`near LOD objects
GLOBAL num_objects_in_landscape AS INTEGER
TEXT 0,0,"Please Wait - Creating Objects"
SYNC
u#=1.0/near_lod
v#=1.0/near_lod
create_memblockobject(1,(near_lod*near_lod*2*3))
`build the near LOD objects
obj=1000
FOR z=0 TO grid_z#/near_lod-1
FOR x=0 TO grid_x#/near_lod-1
build_memblockobject(obj,x*near_lod,z*near_lod,x*near_lod+near_lod,z*near_lod+near_lod)
IF wf=1 THEN SET OBJECT WIREFRAME obj,1
SYNC
INC obj
INC num_objects_in_landscape
NEXT x
NEXT z
`mid LOD objects
u#=1.0/mid_lod
v#=1.0/mid_lod
DIM map_data_lod1(grid_x#/2,grid_z#/2,8) AS FLOAT
create_memblockobject(2,(mid_lod*mid_lod*2*3))
FOR z=0 TO grid_x#/2
FOR x=0 TO grid_z#/2
FOR l=1 TO 8
map_data_lod1(x,z,l)=map_data(x*2,z*2,l)
NEXT l
NEXT x
NEXT z
`build the mid LOD objects
obj=2000
FOR z=0 TO grid_z#/near_lod-1
FOR x=0 TO grid_x#/near_lod-1
build_memblockobject_lod1(obj,x*mid_lod,z*mid_lod,x*mid_lod+mid_lod,z*mid_lod+mid_lod)
IF wf=1 THEN SET OBJECT WIREFRAME obj,1
INC obj
NEXT x
NEXT z
`far LOD objects
u#=1.0/far_lod
v#=1.0/far_lod
DIM map_data_lod2(grid_x#/4,grid_z#/4,8) AS FLOAT
create_memblockobject(3,(far_lod*far_lod*2*3))
FOR z=0 TO grid_z#/4
FOR x=0 TO grid_x#/4
FOR l=1 TO 8
map_data_lod2(x,z,l)=map_data(x*4,z*4,l)
NEXT l
NEXT x
NEXT z
`build the far LOD objects
obj=3000
FOR z=0 TO grid_z#/near_lod-1
FOR x=0 TO grid_x#/near_lod-1
build_memblockobject_lod2(obj,x*far_lod,z*far_lod,x*far_lod+far_lod,z*far_lod+far_lod)
IF wf=1 THEN SET OBJECT WIREFRAME obj,1
INC obj
NEXT x
NEXT z
`######################################################################### TEXTURE CREATION
IF wf=0
TEXT 0,0,"Please Wait - Creating Textures Samples"
SYNC
`make tiles
`sand grass rock
make_sprite(235,180,50,4000):SPRITE 1,-128,-128,4000
make_sprite(205,128,50,4001):SPRITE 2,-128,-128,4001
make_sprite(128,64,50,4002):SPRITE 3,-128,-128,4002
make_sprite(0,200,0,4003):SPRITE 4,-128,-128,4003
make_sprite(0,128,0,4004):SPRITE 5,-128,-128,4004
make_sprite(0,64,0,4005):SPRITE 6,-128,-128,4005
make_sprite(30,30,30,4006):SPRITE 7,-128,-128,4006
make_sprite(70,70,70,4007):SPRITE 8,-128,-128,4007
make_sprite(120,120,120,4008):SPRITE 9,-128,-128,4008
make_sprite(170,170,170,4009):SPRITE 10,-128,-128,4009
make_sprite(220,220,220,4010):SPRITE 11,-128,-128,4010
ENDIF
IF wf=0
TEXT 0,0,"Please Wait - Applying Textures To Near LOD"
SYNC
bitmap_size#=512
preview_texture(bmp$,1000)
ENDIF
`######################################################################### ADD LOD OBJECTS
`set up the LOD data if textures are needed then call this after they have been set up as once this is called no changes can be made
FOR l=1000 TO (grid_x#/near_lod)*(grid_z#/near_lod)+999
ADD LOD TO OBJECT l,l+1000,0,near_lod*grid_size#*2
ADD LOD TO OBJECT l,l+2000,1,near_lod*grid_size#*3
DELETE OBJECT l+1000
DELETE OBJECT l+2000
NEXT l
`reset uv to main texture size
u#=1.0/near_lod
v#=1.0/near_lod
`###################################################################### MAIN LOOP
CLS
SYNC
DO
mov#=(2000.0-SCREEN FPS())/500.0
mousecontrol(8)
IF INKEY$()="z"
POSITION CAMERA -1000,3000,-1000
POINT CAMERA 3000,0,3000
SET POINT LIGHT 1,5000,5000,5000
SET LIGHT RANGE 1,50000
ENDIF
lx=LIGHT POSITION X(1)
ly=LIGHT POSITION Y(1)
lz=LIGHT POSITION Z(1)
`control light
IF UPKEY()
POSITION LIGHT 1,lx,ly,lz+10
ENDIF
IF DOWNKEY()
POSITION LIGHT 1,lx,ly,lz-10
ENDIF
IF LEFTKEY()
POSITION LIGHT 1,lx-10,ly,lz
ENDIF
IF RIGHTKEY()
POSITION LIGHT 1,lx+10,ly,lz
ENDIF
POSITION OBJECT 10000,lx,ly,lz
IF INKEY$()="-"
SET LIGHT RANGE 1,LIGHT RANGE(1)-100
ENDIF
IF INKEY$()="+"
SET LIGHT RANGE 1,LIGHT RANGE(1)+100
ENDIF
TEXT 0,0,"press 'z' to reset view point"
TEXT 0,30,"mouse to look around"
TEXT 0,60,"arrows to move light,'+','-' to change range - position x"+STR$(lx)+" y"+STR$(ly)+" z"+STR$(lz)+" range "+STR$(INT(LIGHT RANGE(1)))
TEXT 0,90,"screen fps "+STR$(SCREEN FPS())
// text 0,120,"'w' to turn wire frame test mode on (puts closest LOD into wire frame only)"
TEXT 0,150,"Polygons on screen "+STR$(STATISTIC(1))+" mov "+STR$(mov#)
SYNC
// IF INKEY$()="w"
// INC wf
// if wf>1 then wf=0
// FOR l=1000 TO 1000+num_objects_in_landscape-1
// SET OBJECT WIREFRAME l,wf
// NEXT l
// FOR w=0 TO 100000
// ``wait
// NEXT w
// ENDIF
LOOP
`###################################################################### FUNCTIONS
FUNCTION read_hmap()
IF FILE OPEN(1) THEN CLOSE FILE 1
OPEN TO READ 1,"hmap.raw"
DIM dat(512,512)
FOR z=0 TO 512
FOR x=0 TO 512
READ BYTE 1,bt1
dat(x,z)=bt1
DOT x,z,RGB(bt1,bt1,bt1)
IF x<=grid_x# AND z<=grid_z#
map_data(x,z,1)=bt1*scale
ENDIF
NEXT x
NEXT z
CLOSE FILE 1
SYNC
ENDFUNCTION
FUNCTION hmap_fractal()
`thanks to who ever did this code,had it so long,and it never fails to work for me
av AS FLOAT
rn AS FLOAT
s=grid_x# ` units and array size; must be a power of 2
rn=0.06 ` bigger numbers = smoother, smaller = spikier
smt=1 ` how many times to smooth matrix
DIM a(s,s,1) AS FLOAT
` do the diamond square algorithm
` paying special attention to wrapping around
c=s
REPEAT
FOR z=0 TO (s-c) STEP c
FOR x=0 TO (s-c) STEP c
av=(a(x,z)+a(x+c,z)+a(x,z+c)+a(x+c,z+c))/4.0
av=av+((-50+RND(100))/rn)
a(x+(c/2),z+(c/2))=av
NEXT x
NEXT z
w=1
FOR z=0 TO (s-(c/2)) STEP (c/2)
FOR x=0 TO (s-c) STEP c
x2=x+(w*(c/2))
av=a(x2,z+(c/2))+a(x2+(c/2),z)
IF x2=0
av=av+a(s-(c/2),z)
ELSE
av=av+a(x2-(c/2),z)
ENDIF
IF z=0
av=av+a(x2,s-(c/2))
ELSE
av=av+a(x2,z-(c/2))
ENDIF
av=av/4.0
av=av+((-50+RND(100))/rn)
a(x2,z,0)=av
IF x2=0 THEN a(s,z,0)=av
IF z=0 THEN a(x2,s,0)=av
NEXT x
w=1-w
NEXT z
c=c/2
rn=rn*2.0
UNTIL c < 2
` smooth the result
FOR multiple=1 TO smt
FOR x=0 TO s-1
x2=x-1 : IF x2 < 0 THEN x2=s-1
FOR z=0 TO s-1
z2=z-1 : IF z2 < 0 THEN z2=s-1
v1#=a(x2,z+1,0)
v2#=a(x,z+1,0)
v3#=a(x+1,z+1,0)
v4#=a(x+1,z,0)
v5#=a(x+1,z2,0)
v6#=a(x,z2,0)
v7#=a(x2,z2,0)
v8#=a(x2,z,0)
av#=(v1#+v2#+v3#+v4#+v5#+v6#+v7#+v8#)/8.0
a(x,z,0)=av#
NEXT z
NEXT x
FOR f=0 TO s
a(s,f,0)=a(0,f,0)
a(f,s,0)=a(f,0,0)
NEXT f
NEXT multiple
`find min/max height
minh#=5000:maxh#=-5000
FOR z=0 TO grid_z#
FOR x=0 TO grid_x#
a(x,z,0)=a(x,z,0)*scale
IF a(x,z,0)<minh# THEN minh#=a(x,z,0)
IF a(x,z,0)>maxh# THEN maxh#=a(x,z,0)
NEXT x
NEXT z
` update data array and make it raise up so the lowest point is>=0
FOR z=0 TO grid_z#
FOR x=0 TO grid_x#
av=a(x,z,0)
IF minh#<0 THEN map_data(x,z,1)=av+ABS(minh#)
IF minh#>=0 THEN map_data(x,z,1)=av-minh#
`resets the normals
map_data(x,z,2)=0
map_data(x,z,3)=0
map_data(x,z,4)=0
map_data(x,z,5)=0
NEXT x
NEXT z
`set up texture heights to suit terrain created
diff#=maxh#-minh#
diff#=diff#/100.0
`sand grass rock
sand1#=(diff#*10)
sand2#=(diff#*15)
sand3#=(diff#*20)
grass1#=(diff#*30)
grass2#=(diff#*50)
grass3#=(diff#*70)
rock1#=(diff#*75)
rock2#=(diff#*80)
rock3#=(diff#*85)
rock4#=(diff#*90)
rock5#=(diff#*95)
`random variation based on this value
hmv#=diff#*10`blend between textures so its not striped
blend=64
ENDFUNCTION
FUNCTION create_memblockobject(memnum,v)
MAKE MEMBLOCK memnum,12+(32*v)
WRITE MEMBLOCK DWORD memnum,0,274
WRITE MEMBLOCK DWORD memnum,4,32
WRITE MEMBLOCK DWORD memnum,8,v
ENDFUNCTION
FUNCTION create_vertex(memnum,v,vposx#,vposy#,vposz#,color AS DWORD,u#,v#)
WRITE MEMBLOCK FLOAT memnum,v*32+12,vposx#
WRITE MEMBLOCK FLOAT memnum,v*32+16,vposy#
WRITE MEMBLOCK FLOAT memnum,v*32+20,vposz#
`write memblock dword memnum,v*36+36,color `not needed in 274fvf format diffuse color seems to mess up some shader code
WRITE MEMBLOCK FLOAT memnum,v*32+36,u#
WRITE MEMBLOCK FLOAT memnum,v*32+40,v#
ENDFUNCTION
FUNCTION set_normal(memnum,v,normalx#,normaly#,normalz#)
WRITE MEMBLOCK FLOAT memnum,v*32+24,normalx#
WRITE MEMBLOCK FLOAT memnum,v*32+28,normaly#
WRITE MEMBLOCK FLOAT memnum,v*32+32,normalz#
ENDFUNCTION
FUNCTION make_object(objnum,meshnum,memnum,imgnum)
IF OBJECT EXIST (objnum) THEN DELETE OBJECT objnum
IF MESH EXIST (meshnum) THEN DELETE MESH meshnum
MAKE MESH FROM MEMBLOCK meshnum,memnum
MAKE OBJECT objnum,meshnum,imgnum
ENDFUNCTION
FUNCTION make_normals()
FOR z=0 TO grid_z#-1
FOR x=0 TO grid_x#-1
x1#=x*grid_size#:y1#=map_data(x,z,1):z1#=z*grid_size#
x2#=x*grid_size#:y2#=map_data(x,z+1,1):z2#=(z+1)*grid_size#
x3#=(x+1)*grid_size#:y3#=map_data(x+1,z,1):z3#=z*grid_size#
`find the surface normal of the polygon
IF ez=1
EZRO_FINDNORMAL x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3#
xn#=EZRO_GETNORMALX()
yn#=EZRO_GETNORMALY()
zn#=EZRO_GETNORMALZ()
ENDIF
IF ez=0
normals(x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3#)
xn#=avx#
yn#=avy#
zn#=avz#
ENDIF
`add it to any others at that vertex and increment the number of times that vertex has been used
map_data(x,z,2)=map_data(x,z,2)+xn#
map_data(x,z,3)=map_data(x,z,3)+yn#
map_data(x,z,4)=map_data(x,z,4)+zn#
INC map_data(x,z,5)
map_data(x,z+1,2)=map_data(x,z+1,2)+xn#
map_data(x,z+1,3)=map_data(x,z+1,3)+yn#
map_data(x,z+1,4)=map_data(x,z+1,4)+zn#
INC map_data(x,z+1,5)
map_data(x+1,z,2)=map_data(x+1,z,2)+xn#
map_data(x+1,z,3)=map_data(x+1,z,3)+yn#
map_data(x+1,z,4)=map_data(x+1,z,4)+zn#
INC map_data(x+1,z,5)
x1#=(x+1)*grid_size#:y1#=map_data(x+1,z+1,1):z1#=(z+1)*grid_size#
x2#=(x+1)*grid_size#:y2#=map_data(x+1,z,1):z2#=z*grid_size#
x3#=x*grid_size#:y3#=map_data(x,z+1,1):z3#=(z+1)*grid_size#
`find the surface normal of the polygon
IF ez=1
EZRO_FINDNORMAL x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3#
xn#=EZRO_GETNORMALX()
yn#=EZRO_GETNORMALY()
zn#=EZRO_GETNORMALZ()
ENDIF
IF ez=0
normals(x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3#)
xn#=avx#
yn#=avy#
zn#=avz#
ENDIF
`add it to any others at that vertex and increment the number of times that vertex has been used
map_data(x+1,z+1,2)=map_data(x+1,z+1,2)+xn#
map_data(x+1,z+1,3)=map_data(x+1,z+1,3)+yn#
map_data(x+1,z+1,4)=map_data(x+1,z+1,4)+zn#
INC map_data(x+1,z+1,5)
map_data(x+1,z,2)=map_data(x+1,z,2)+xn#
map_data(x+1,z,3)=map_data(x+1,z,3)+yn#
map_data(x+1,z,4)=map_data(x+1,z,4)+zn#
INC map_data(x,z+1,5)
map_data(x,z+1,2)=map_data(x,z+1,2)+xn#
map_data(x,z+1,3)=map_data(x,z+1,3)+yn#
map_data(x,z+1,4)=map_data(x,z+1,4)+zn#
INC map_data(x+1,z,5)
NEXT x
NEXT z
`average the normals at each point
FOR z=0 TO grid_z#
FOR x=0 TO grid_x#
dumx#=map_data(x,z,2)/map_data(x,z,5)
dumy#=map_data(x,z,3)/map_data(x,z,5)
dumz#=map_data(x,z,4)/map_data(x,z,5)
`dumx#=4.0
`dumy#=4.0
`dumz#=4.0
map_data(x,z,2)=dumx#
map_data(x,z,3)=dumy#
map_data(x,z,4)=dumz#
NEXT x
NEXT z
ENDFUNCTION
FUNCTION normals(vertex_px1#,vertex_py1#,vertex_pz1#,vertex_px2#,vertex_py2#,vertex_pz2#,vertex_px3#,vertex_py3#,vertex_pz3#)
`zero globals
avx#=0
avy#=0
avz#=0
`vertex 1
SET VECTOR3 0,vertex_px1#, vertex_py1#, vertex_pz1#
`vertex 2
SET VECTOR3 1,vertex_px2#, vertex_py2#, vertex_pz2#
`vertex 3
SET VECTOR3 2,vertex_px3#, vertex_py3#, vertex_pz3#
`find normals
SUBTRACT VECTOR3 5, 0,2 ` -- direction v1
SUBTRACT VECTOR3 6, 1,2 ` -- direction v2
CROSS PRODUCT VECTOR3 9, 5,6 ` -- normal
NORMALIZE VECTOR3 10, 9 ` -- normalized normal
`set globals to vector results
avx#=X VECTOR3(10)
avy#=Y VECTOR3(10)
avz#=Z VECTOR3(10)
ENDFUNCTION
FUNCTION build_memblockobject(obj,start_x,start_z,end_x,end_z)
vertex=0
FOR z=start_z TO end_z-1
FOR x=start_x TO end_x-1
x1#=x*grid_size#:y1#=map_data(x,z,1):z1#=z*grid_size#
x2#=x*grid_size#:y2#=map_data(x,z+1,1):z2#=(z+1)*grid_size#
x3#=(x+1)*grid_size#:y3#=map_data(x+1,z,1):z3#=z*grid_size#
x1#=x1#-(start_x*grid_size#):x2#=x2#-(start_x*grid_size#):x3#=x3#-(start_x*grid_size#)
z1#=z1#-(start_z*grid_size#):z2#=z2#-(start_z*grid_size#):z3#=z3#-(start_z*grid_size#)
create_vertex(1,vertex,x1#,y1#,z1#,RGB(map_data(x,z,6),map_data(x,z,7),map_data(x,z,8)),u#*(x-start_x),v#*(z-start_z))
set_normal(1,vertex,map_data(x,z,2),map_data(x,z,3),map_data(x,z,4))
INC vertex
create_vertex(1,vertex,x2#,y2#,z2#,RGB(map_data(x,z,6),map_data(x,z,7),map_data(x,z,8)),u#*(x-start_x),v#*(z+1-start_z))
set_normal(1,vertex,map_data(x,z+1,2),map_data(x,z+1,3),map_data(x,z+1,4))
INC vertex
create_vertex(1,vertex,x3#,y3#,z3#,RGB(map_data(x,z,6),map_data(x,z,7),map_data(x,z,8)),u#*(x+1-start_x),v#*(z-start_z))
set_normal(1,vertex,map_data(x+1,z,2),map_data(x+1,z,3),map_data(x+1,z,4))
INC vertex
x1#=(x+1)*grid_size#:y1#=map_data(x+1,z+1,1):z1#=(z+1)*grid_size#
x2#=(x+1)*grid_size#:y2#=map_data(x+1,z,1):z2#=z*grid_size#
x3#=x*grid_size#:y3#=map_data(x,z+1,1):z3#=(z+1)*grid_size#
x1#=x1#-(start_x*grid_size#):x2#=x2#-(start_x*grid_size#):x3#=x3#-(start_x*grid_size#)
z1#=z1#-(start_z*grid_size#):z2#=z2#-(start_z*grid_size#):z3#=z3#-(start_z*grid_size#)
create_vertex(1,vertex,x1#,y1#,z1#,RGB(map_data(x,z,6),map_data(x,z,7),map_data(x,z,8)),u#*(x+1-start_x),v#*(z+1-start_z))
set_normal(1,vertex,map_data(x+1,z+1,2),map_data(x+1,z+1,3),map_data(x+1,z+1,4))
INC vertex
create_vertex(1,vertex,x2#,y2#,z2#,RGB(map_data(x,z,6),map_data(x,z,7),map_data(x,z,8)),u#*(x+1-start_x),v#*(z-start_z))
set_normal(1,vertex,map_data(x+1,z,2),map_data(x+1,z,3),map_data(x+1,z,4))
INC vertex
create_vertex(1,vertex,x3#,y3#,z3#,RGB(map_data(x,z,6),map_data(x,z,7),map_data(x,z,8)),u#*(x-start_x),v#*(z+1-start_z))
set_normal(1,vertex,map_data(x,z+1,2),map_data(x,z+1,3),map_data(x,z+1,4))
INC vertex
NEXT x
NEXT z
make_object(obj,1,1,0)
POSITION OBJECT obj,start_x*grid_size#,OBJECT POSITION Y(obj),start_z*grid_size#
IF save=1
f$=dbo$+"\land mass"+STR$(obj)+".dbo"
IF FILE EXIST(f$) THEN DELETE FILE f$
SAVE OBJECT f$,obj
ENDIF
ENDFUNCTION
FUNCTION build_memblockobject_lod1(obj,start_x,start_z,end_x,end_z)
vertex=0
FOR z=start_z TO end_z-1
FOR x=start_x TO end_x-1
x1#=x*grid_size#*2:y1#=map_data_lod1(x,z,1):z1#=z*grid_size#*2
x2#=x*grid_size#*2:y2#=map_data_lod1(x,z+1,1):z2#=(z+1)*grid_size#*2
x3#=(x+1)*grid_size#*2:y3#=map_data_lod1(x+1,z,1):z3#=z*grid_size#*2
x1#=x1#-(start_x*grid_size#*2):x2#=x2#-(start_x*grid_size#*2):x3#=x3#-(start_x*grid_size#*2)
z1#=z1#-(start_z*grid_size#*2):z2#=z2#-(start_z*grid_size#*2):z3#=z3#-(start_z*grid_size#*2)
create_vertex(2,vertex,x1#,y1#,z1#,RGB(map_data_lod1(x,z,6),map_data_lod1(x,z,7),map_data_lod1(x,z,8)),u#*(x-start_x),v#*(z-start_z))
set_normal(2,vertex,map_data_lod1(x,z,2),map_data_lod1(x,z,3),map_data_lod1(x,z,4))
INC vertex
create_vertex(2,vertex,x2#,y2#,z2#,RGB(map_data_lod1(x,z,6),map_data_lod1(x,z,7),map_data_lod1(x,z,8)),u#*(x-start_x),v#*(z+1-start_z))
set_normal(2,vertex,map_data_lod1(x,z+1,2),map_data_lod1(x,z+1,3),map_data_lod1(x,z+1,4))
INC vertex
create_vertex(2,vertex,x3#,y3#,z3#,RGB(map_data_lod1(x,z,6),map_data_lod1(x,z,7),map_data_lod1(x,z,8)),u#*(x+1-start_x),v#*(z-start_z))
set_normal(2,vertex,map_data_lod1(x+1,z,2),map_data_lod1(x+1,z,3),map_data_lod1(x+1,z,4))
INC vertex
x1#=(x+1)*grid_size#*2:y1#=map_data_lod1(x+1,z+1,1):z1#=(z+1)*grid_size#*2
x2#=(x+1)*grid_size#*2:y2#=map_data_lod1(x+1,z,1):z2#=z*grid_size#*2
x3#=x*grid_size#*2:y3#=map_data_lod1(x,z+1,1):z3#=(z+1)*grid_size#*2
x1#=x1#-(start_x*grid_size#*2):x2#=x2#-(start_x*grid_size#*2):x3#=x3#-(start_x*grid_size#*2)
z1#=z1#-(start_z*grid_size#*2):z2#=z2#-(start_z*grid_size#*2):z3#=z3#-(start_z*grid_size#*2)
create_vertex(2,vertex,x1#,y1#,z1#,RGB(map_data_lod1(x,z,6),map_data_lod1(x,z,7),map_data_lod1(x,z,8)),u#*(x+1-start_x),v#*(z+1-start_z))
set_normal(2,vertex,map_data_lod1(x+1,z+1,2),map_data_lod1(x+1,z+1,3),map_data_lod1(x+1,z+1,4))
INC vertex
create_vertex(2,vertex,x2#,y2#,z2#,RGB(map_data_lod1(x,z,6),map_data_lod1(x,z,7),map_data_lod1(x,z,8)),u#*(x+1-start_x),v#*(z-start_z))
set_normal(2,vertex,map_data_lod1(x+1,z,2),map_data_lod1(x+1,z,3),map_data_lod1(x+1,z,4))
INC vertex
create_vertex(2,vertex,x3#,y3#,z3#,RGB(map_data_lod1(x,z,6),map_data_lod1(x,z,7),map_data_lod1(x,z,8)),u#*(x-start_x),v#*(z+1-start_z))
set_normal(2,vertex,map_data_lod1(x,z+1,2),map_data_lod1(x,z+1,3),map_data_lod1(x,z+1,4))
INC vertex
NEXT x
NEXT z
make_object(obj,2,2,0)
IF save=1
f$=dbo$+"lod1"+"\land mass"+STR$(obj)+".dbo"
IF FILE EXIST(f$) THEN DELETE FILE f$
SAVE OBJECT f$,obj
ENDIF
POSITION OBJECT obj,-5000,-5000,-5000
ENDFUNCTION
FUNCTION build_memblockobject_lod2(obj,start_x,start_z,end_x,end_z)
vertex=0
FOR z=start_z TO end_z-1
FOR x=start_x TO end_x-1
x1#=x*grid_size#*4:y1#=map_data_lod2(x,z,1):z1#=z*grid_size#*4
x2#=x*grid_size#*4:y2#=map_data_lod2(x,z+1,1):z2#=(z+1)*grid_size#*4
x3#=(x+1)*grid_size#*4:y3#=map_data_lod2(x+1,z,1):z3#=z*grid_size#*4
x1#=x1#-(start_x*grid_size#*4):x2#=x2#-(start_x*grid_size#*4):x3#=x3#-(start_x*grid_size#*4)
z1#=z1#-(start_z*grid_size#*4):z2#=z2#-(start_z*grid_size#*4):z3#=z3#-(start_z*grid_size#*4)
create_vertex(3,vertex,x1#,y1#,z1#,RGB(map_data_lod2(x,z,6),map_data_lod2(x,z,7),map_data_lod2(x,z,8)),u#*(x-start_x),v#*(z-start_z))
set_normal(3,vertex,map_data_lod2(x,z,2),map_data_lod2(x,z,3),map_data_lod2(x,z,4))
INC vertex
create_vertex(3,vertex,x2#,y2#,z2#,RGB(map_data_lod2(x,z,6),map_data_lod2(x,z,7),map_data_lod2(x,z,8)),u#*(x-start_x),v#*(z+1-start_z))
set_normal(3,vertex,map_data_lod2(x,z+1,2),map_data_lod2(x,z+1,3),map_data_lod2(x,z+1,4))
INC vertex
create_vertex(3,vertex,x3#,y3#,z3#,RGB(map_data_lod2(x,z,6),map_data_lod2(x,z,7),map_data_lod2(x,z,8)),u#*(x+1-start_x),v#*(z-start_z))
set_normal(3,vertex,map_data_lod2(x+1,z,2),map_data_lod2(x+1,z,3),map_data_lod2(x+1,z,4))
INC vertex
x1#=(x+1)*grid_size#*4:y1#=map_data_lod2(x+1,z+1,1):z1#=(z+1)*grid_size#*4
x2#=(x+1)*grid_size#*4:y2#=map_data_lod2(x+1,z,1):z2#=z*grid_size#*4
x3#=x*grid_size#*4:y3#=map_data_lod2(x,z+1,1):z3#=(z+1)*grid_size#*4
x1#=x1#-(start_x*grid_size#*4):x2#=x2#-(start_x*grid_size#*4):x3#=x3#-(start_x*grid_size#*4)
z1#=z1#-(start_z*grid_size#*4):z2#=z2#-(start_z*grid_size#*4):z3#=z3#-(start_z*grid_size#*4)
create_vertex(3,vertex,x1#,y1#,z1#,RGB(map_data_lod2(x,z,6),map_data_lod2(x,z,7),map_data_lod2(x,z,8)),u#*(x+1-start_x),v#*(z+1-start_z))
set_normal(3,vertex,map_data_lod2(x+1,z+1,2),map_data_lod2(x+1,z+1,3),map_data_lod2(x+1,z+1,4))
INC vertex
create_vertex(3,vertex,x2#,y2#,z2#,RGB(map_data_lod2(x,z,6),map_data_lod2(x,z,7),map_data_lod2(x,z,8)),u#*(x+1-start_x),v#*(z-start_z))
set_normal(3,vertex,map_data_lod2(x+1,z,2),map_data_lod2(x+1,z,3),map_data_lod2(x+1,z,4))
INC vertex
create_vertex(3,vertex,x3#,y3#,z3#,RGB(map_data_lod2(x,z,6),map_data_lod2(x,z,7),map_data_lod2(x,z,8)),u#*(x-start_x),v#*(z+1-start_z))
set_normal(3,vertex,map_data_lod2(x,z+1,2),map_data_lod2(x,z+1,3),map_data_lod2(x,z+1,4))
INC vertex
NEXT x
NEXT z
make_object(obj,3,3,0)
IF save=1
f$=dbo$+"lod2"+"\land mass"+STR$(obj)+".dbo"
IF FILE EXIST(f$) THEN DELETE FILE f$
SAVE OBJECT f$,obj
POSITION OBJECT obj,-5000,-5000,-5000
ENDIF
ENDFUNCTION
FUNCTION mousecontrol(Speed AS FLOAT)
XROTATE CAMERA CAMERA ANGLE X()+MOUSEMOVEY()
YROTATE CAMERA CAMERA ANGLE Y()+MOUSEMOVEX()
IF MOUSECLICK()=1 THEN MOVE CAMERA Speed
IF MOUSECLICK()=2 THEN MOVE CAMERA (0-Speed)
r=MOUSEMOVEX()
r=MOUSEMOVEY()
ENDFUNCTION
`###################################################################### TEXTURE ROUTINES STAR HERE
FUNCTION make_sprite(r#,g#,b#,image_num)
IF BITMAP EXIST(1) THEN DELETE BITMAP 1
SET BITMAP FORMAT 21
CREATE BITMAP 1,128,128
SET CURRENT BITMAP 1
SET IMAGE COLORKEY 0,0,0
FOR l=1 TO 2000
x=RND(128)
z=RND(128)
DOT x,z,RGB(r#,g#,b#)
NEXT l
FOR l=1 TO 2000
x=RND(128)
z=RND(128)
col#=RND(30)
r2#=r#+col#
IF r2#>255 THEN r2#=255
g2#=g#+col#
IF g2#>255 THEN g2#=255
b2#=b#+col#
IF b2#>255 THEN b2#=255
DOT x,z,RGB(r2#,g2#,b2#)
NEXT l
FOR l=1 TO 200
x=RND(128)
z=RND(128)
col#=RND(50)+50
r2#=col#
g2#=col#
b2#=col#
DOT x,z,RGB(r2#,g2#,b2#)
NEXT l
IF IMAGE EXIST(image_num) THEN DELETE IMAGE image_num
GET IMAGE image_num,0,0,128,128
IF save=1
f$=bmp$+"\sprite"+STR$(image_num)+".png"
IF FILE EXIST(f$) THEN DELETE FILE f$
SAVE IMAGE f$,image_num
ENDIF
SET CURRENT BITMAP 0
ENDFUNCTION
FUNCTION preview_texture(bf$,ob)
obj=ob
`make a bitmap big enough to cover the whole 8 x 8 grid
IF BITMAP EXIST(1) THEN DELETE BITMAP 1
SET BITMAP FORMAT 21
bms#=bitmap_size#*(8)
CREATE BITMAP 1,bms#,bms#
SET CURRENT BITMAP 1
mulx=bms#/(64*8)
mulz=bms#/(64*8)
FOR z=0 TO 64*8 `step 2
FOR x=0 TO 64*8 `step 2
IF INKEY$()="q" THEN GOTO jump3
posx=(x*mulx)+RND(blend)-(blend/2)
posz=(z*mulz)+RND(blend)-(blend/2)
offset=RND(hmv#)
IF map_data(x,z,1)<=sand1#-offset
ROTATE SPRITE 1,RND(90)
PASTE SPRITE 1,posx,posz
ENDIF
IF map_data(x,z,1)>sand1#-offset AND map_data(x,z,1)<=sand2#+offset
ROTATE SPRITE 2,RND(90)
PASTE SPRITE 2,posx,posz
ENDIF
IF map_data(x,z,1)>sand2#-offset AND map_data(x,z,1)<=sand3#+offset
ROTATE SPRITE 3,RND(90)
PASTE SPRITE 3,posx,posz
ENDIF
IF map_data(x,z,1)>sand3#-offset AND map_data(x,z,1)<=grass1#+offset
ROTATE SPRITE 4,RND(90)
PASTE SPRITE 4,posx,posz
ENDIF
IF map_data(x,z,1)>grass1#-offset AND map_data(x,z,1)<=grass2#+offset
ROTATE SPRITE 5,RND(90)
PASTE SPRITE 5,posx,posz
ENDIF
IF map_data(x,z,1)>grass2#-offset AND map_data(x,z,1)<=grass3#+offset
ROTATE SPRITE 6,RND(90)
PASTE SPRITE 6,posx,posz
ENDIF
IF map_data(x,z,1)>grass3#-offset AND map_data(x,z,1)<=rock1#+offset
ROTATE SPRITE 7,RND(90)
PASTE SPRITE 7,posx,posz
ENDIF
IF map_data(x,z,1)>rock1#-offset AND map_data(x,z,1)<=rock2#+offset
ROTATE SPRITE 8,RND(90)
PASTE SPRITE 8,posx,posz
ENDIF
IF map_data(x,z,1)>rock2#-offset AND map_data(x,z,1)<=rock3#+offset
ROTATE SPRITE 9,RND(90)
PASTE SPRITE 9,posx,posz
ENDIF
IF map_data(x,z,1)>rock3#-offset AND map_data(x,z,1)<=rock4#+offset
ROTATE SPRITE 10,RND(90)
PASTE SPRITE 10,posx,posz
ENDIF
IF map_data(x,z,1)>rock4#-offset
ROTATE SPRITE 11,RND(90)
PASTE SPRITE 11,posx,posz
ENDIF
NEXT x
NEXT z
`cut up the texture in to tile size pieces and apply to mesh
FOR z=0 TO 7
FOR x=0 TO 7
IF INKEY$()="q" THEN GOTO jump3
GET IMAGE obj,x*bitmap_size#+1,z*bitmap_size#+1,(x+1)*bitmap_size#,(z+1)*bitmap_size#
TEXTURE OBJECT obj,0,obj
SET OBJECT TEXTURE obj,2,1
IF save=1
f$=bf$
f$=f$+"\land mass"+STR$(obj)+".bmp"
IF FILE EXIST(f$) THEN DELETE FILE f$
SAVE IMAGE f$,obj
ENDIF
SET CURRENT BITMAP 0
SYNC
SET CURRENT BITMAP 1
INC obj
NEXT x
NEXT z
SET CURRENT BITMAP 0
jump3:
SET CURRENT BITMAP 0
IF BITMAP EXIST(1) THEN DELETE BITMAP 1
ENDFUNCTION
Hope this helps,i have a lot of other code for vertex manipulation as well if your still stuck,but i have to say that trying to implement LOD at this stage is a bit late,i think you you may find its easier to design the code with it in mind from the start than add it in later,i know i tried it the hard way first!