// Project: CreateObjectMeshMemblock // Created: 24-04-26 // show all errors SetErrorMode(2) // set window properties SetWindowTitle( "Create a clustered meshed Map" ) SetWindowSize( 1600, 900, 0 ) SetWindowAllowResize( 1 ) // allow the user to resize the window // set display properties SetVirtualResolution( 1600, 900 ) // doesn't have to match the window SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices SetSyncRate( 120, 0 ) // 30fps instead of 60 to save battery SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders UseNewDefaultFonts( 1 ) //---------------------------------------------------------------------- // help and controls //---------------------------------------------------------------------- // (w) (up) move camera forward // (s) (down) move camera backward // (a) (left) move camera left // (d) (right) move camera right // (q) rotate camera left around center // (e) rotate camera right around center // (page up) increase map clip level // (page down) decrease map clip level //---------------------------------------------------------------------- // fast setup the world size here //---------------------------------------------------------------------- #constant WorldX 50 // size of world x expansion = tile count x (mult of cluster size x) #constant WorldY 5 // size of world y expansion = tile count y #constant WorldZ 50 // size of world z expansion = tile count z (mult of cluster size z) #constant ClusterX 20 // size of cluster x expansion #constant ClusterZ 20 // size of cluster z expansion #constant TileSize 5 // tile size = mesh size in world units #constant MountainNoise 0 // simple noise generator 0 = off / 1 = max / >1 = min #constant MountainCount 3 // count of the generated mountains #constant MountainHeight 100 // in Percent #constant MountainExpansion 15 // in Percent #constant TexMax 10 // max count of different textures for ground and cliff #constant CamAngle 30 // 30 = iso #constant CamHeight 45 #constant CamRange 250 #constant CamStep 5 // world units #constant CamDelay 30 // millisecs //---------------------------------------------------------------------- // key const //---------------------------------------------------------------------- #constant KEY_BACK 8 #constant KEY_TAB 9 #constant KEY_ENTER 13 #constant KEY_SHIFT 16 #constant KEY_CONTROL 17 #constant KEY_ESCAPE 27 #constant KEY_SPACE 32 #constant KEY_PAGEUP 33 #constant KEY_PAGEDOWN 34 #constant KEY_END 35 #constant KEY_HOME 36 #constant KEY_LEFT 37 #constant KEY_UP 38 #constant KEY_RIGHT 39 #constant KEY_DOWN 40 #constant KEY_INSERT 45 #constant KEY_DELETE 46 #constant KEY_0 48 #constant KEY_1 49 #constant KEY_2 50 #constant KEY_3 51 #constant KEY_4 52 #constant KEY_5 53 #constant KEY_6 54 #constant KEY_7 55 #constant KEY_8 56 #constant KEY_9 57 #constant KEY_A 65 #constant KEY_B 66 #constant KEY_C 67 #constant KEY_D 68 #constant KEY_E 69 #constant KEY_F 70 #constant KEY_G 71 #constant KEY_H 72 #constant KEY_I 73 #constant KEY_J 74 #constant KEY_K 75 #constant KEY_L 76 #constant KEY_M 77 #constant KEY_N 78 #constant KEY_O 79 #constant KEY_P 80 #constant KEY_Q 81 #constant KEY_R 82 #constant KEY_S 83 #constant KEY_T 84 #constant KEY_U 85 #constant KEY_V 86 #constant KEY_W 87 #constant KEY_X 88 #constant KEY_Y 89 #constant KEY_Z 90 #constant KEY_F1 112 #constant KEY_F2 113 #constant KEY_F3 114 #constant KEY_F4 115 #constant KEY_F5 116 #constant KEY_F6 117 #constant KEY_F7 118 #constant KEY_F8 119 #constant KEY_S1 186 #constant KEY_S2 187 #constant KEY_S3 188 #constant KEY_S4 189 #constant KEY_S5 190 #constant KEY_S6 191 #constant KEY_S7 192 #constant KEY_S8 219 #constant KEY_S9 220 #constant KEY_S10 221 #constant KEY_S11 222 #constant KEY_S12 223 //---------------------------------------------------------------------- // create type for the mesh to pass by ref //---------------------------------------------------------------------- type TMesh Normal as integer UV as integer Color as integer Memblock as integer Vertices as integer VertexOffset as integer Indices as integer IndexOffset as integer x as float y as float z as float Size as float endtype //---------------------------------------------------------------------- // create the mesh memblock header //---------------------------------------------------------------------- function SetMeshMemblockHeader(Mesh ref as TMesh) Error = 0 // set mesh memblock header data for a simple plane Mesh.Vertices = 4 // min points needed Mesh.Indices = 6 // min points for triangles Attributes = 1 // min attribute is 1 for position // add attributes if enabled if Mesh.Normal = 1 then inc Attributes if Mesh.UV = 1 then inc Attributes if Mesh.Color = 1 then inc Attributes // additional attributes count must add her // ... // main header block end -> attribute pos in header MainSize = 24 // measure the attribute block // position is a must have PositionSize = 4 + 12 PositionOffset = MainSize VertexSize = 3 * 4 Offset = PositionOffset + PositionSize // add dynamic attributes // normals for light NormalSize = 4 + 8 NormalOffset = Mesh.Normal * Offset VertexSize = VertexSize + Mesh.Normal * 3 * 4 Offset = Offset + Mesh.Normal * NormalSize // uv for texture UVSize = 4 + 4 UVOffset = Mesh.UV * Offset VertexSize = VertexSize + Mesh.UV * 2 * 4 Offset = Offset + Mesh.UV * UVSize // vertex colors ColorSize = 4 + 8 ColorOffset = Mesh.Color * Offset VertexSize = VertexSize + Mesh.Color * 4 Offset = Offset + Mesh.Color * ColorSize // more additional attributes must added here // ... // position of vertex paylod Mesh.VertexOffset = Offset // index size for triangle points remember it's integer not float IndexSize = 4 // position of index payload Mesh.IndexOffset = Mesh.VertexOffset + VertexSize * Mesh.Vertices // prophesy the memblock size for the plane MemblockSize = MainSize + PositionSize MemblockSize = MemblockSize + Mesh.Normal * NormalSize MemblockSize = MemblockSize + Mesh.UV * UVSize MemblockSize = MemblockSize + Mesh.Color * ColorSize // size of additinal attributes must added here // ... MemblockSize = MemblockSize + VertexSize * Mesh.Vertices MemblockSize = MemblockSize + IndexSize * Mesh.Indices if MemblockSize <> Mesh.IndexOffset + IndexSize * Mesh.Indices Error = 1 else // create a memblock object Mesh.Memblock = CreateMemblock(MemblockSize) // write memblock for a plane // the header block for basic usage SetMemblockInt(Mesh.Memblock,0,Mesh.Vertices) // vertex count (min points) SetMemblockInt(Mesh.Memblock,4,Mesh.Indices) // indice count (min 2 triangles * 3 points) SetMemblockInt(Mesh.Memblock,8,Attributes) // attribute count (position, normals, uv, color) SetMemblockInt(Mesh.Memblock,12,VertexSize) // size of vertex data from defined attributes (8 floats + 4 color bytes) SetMemblockInt(Mesh.Memblock,16,Mesh.VertexOffset) SetMemblockInt(Mesh.Memblock,20,Mesh.IndexOffset) // only basic attributes // for other attributes count is a new calculation for offsets needed // no idea for a good generic solution // attribute discription position SetMemblockByte(Mesh.Memblock,PositionOffset+0,0) // float type SetMemblockByte(Mesh.Memblock,PositionOffset+1,3) // 3 components (x,y,z) SetMemblockByte(Mesh.Memblock,PositionOffset+2,0) // normalize 0 (normalize is only for colors needed) SetMemblockByte(Mesh.Memblock,PositionOffset+3,12) // 8 character + 1 nul terminator Round up to = 12 SetMemblockString(Mesh.Memblock,PositionOffset+4,"position") // can be all you mind // attribute discription normals vector -1, 0 and 1 // no normal no light if Mesh.Normal = 1 SetMemblockByte(Mesh.Memblock,NormalOffset+0,0) SetMemblockByte(Mesh.Memblock,NormalOffset+1,3) SetMemblockByte(Mesh.Memblock,NormalOffset+2,0) SetMemblockByte(Mesh.Memblock,NormalOffset+3,8) SetMemblockString(Mesh.Memblock,NormalOffset+4,"normal") endif // attribute discription uv 0.0 - 1.0 // no uv no sunburn no texture if Mesh.UV = 1 SetMemblockByte(Mesh.Memblock,UVOffset+0,0) SetMemblockByte(Mesh.Memblock,UVOffset+1,2) SetMemblockByte(Mesh.Memblock,UVOffset+2,0) SetMemblockByte(Mesh.Memblock,UVOffset+3,4) SetMemblockString(Mesh.Memblock,UVOffset+4,"uv") endif // attribute discription color 0 - 255 * 4 // not clear if needed except for rainbow unicorns if Mesh.Color = 1 SetMemblockByte(Mesh.Memblock,ColorOffset+0,1) SetMemblockByte(Mesh.Memblock,ColorOffset+1,4) SetMemblockByte(Mesh.Memblock,ColorOffset+2,1) SetMemblockByte(Mesh.Memblock,ColorOffset+3,8) SetMemblockString(Mesh.Memblock,ColorOffset+4,"color") endif endif endfunction Error //---------------------------------------------------------------------- // create the mesh memblock payload for plane //---------------------------------------------------------------------- function SetMeshMemblockSimplePlane(Mesh ref as TMesh) // the payload for the memblock // write vertex data // first Corner 0,0 SetMeshMemblockVertexPosition(Mesh.Memblock,0,0,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,0,0,1,0) if Mesh.UV = 1 then SetMeshMemblockVertexUV(Mesh.Memblock,0,0,0) if Mesh.Color = 1 then SetMeshMemblockVertexColor(Mesh.Memblock,0,255,255,255,255) // second corner 0,1 SetMeshMemblockVertexPosition(Mesh.Memblock,1,0,0,Mesh.Size) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,1,0,1,0) if Mesh.UV = 1 then SetMeshMemblockVertexUV(Mesh.Memblock,1,0,1) if Mesh.Color = 1 then SetMeshMemblockVertexColor(Mesh.Memblock,1,255,255,255,255) // third corner 1,1 SetMeshMemblockVertexPosition(Mesh.Memblock,2,Mesh.Size,0,Mesh.Size) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,2,0,1,0) if Mesh.UV = 1 then SetMeshMemblockVertexUV(Mesh.Memblock,2,1,1) if Mesh.Color = 1 then SetMeshMemblockVertexColor(Mesh.Memblock,2,255,255,255,255) // fourth corner 1,0 SetMeshMemblockVertexPosition(Mesh.Memblock,3,Mesh.Size,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,3,0,1,0) if Mesh.UV = 1 then SetMeshMemblockVertexUV(Mesh.Memblock,3,1,0) if Mesh.Color = 1 then SetMeshMemblockVertexColor(Mesh.Memblock,3,255,255,255,255) // write the index data // keep direction of triangles for top view of Plane SetMemblockInt(Mesh.Memblock,Mesh.IndexOffset,0) SetMemblockInt(Mesh.Memblock,Mesh.IndexOffset+4,3) SetMemblockInt(Mesh.Memblock,Mesh.IndexOffset+8,1) SetMemblockInt(Mesh.Memblock,Mesh.IndexOffset+12,2) SetMemblockInt(Mesh.Memblock,Mesh.IndexOffset+16,1) SetMemblockInt(Mesh.Memblock,Mesh.IndexOffset+20,3) endfunction //---------------------------------------------------------------------- // set only the position of mesh ground plane for cluster object //---------------------------------------------------------------------- function SetMeshMemblockGroundPlanePosition(Mesh ref as TMesh) SetMeshMemblockVertexPosition(Mesh.Memblock,0,Mesh.x,Mesh.y,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,1,Mesh.x,Mesh.y,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,2,Mesh.x+Mesh.Size,Mesh.y,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,3,Mesh.x+Mesh.Size,Mesh.y,Mesh.z) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,0,0,1,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,1,0,1,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,2,0,1,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,3,0,1,0) endfunction //---------------------------------------------------------------------- // set only the position of mesh cliff plane for cluster object //---------------------------------------------------------------------- // SouthEast function SetMeshMemblockGroundPlaneSouthEastPosition(Mesh ref as TMesh) SetMeshMemblockVertexPosition(Mesh.Memblock,0,Mesh.x,Mesh.y-Mesh.Size,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,1,Mesh.x,Mesh.y,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,2,Mesh.x+Mesh.Size,Mesh.y,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,3,Mesh.x+Mesh.Size,Mesh.y-Mesh.Size,Mesh.z) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,0,0,0,-1) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,1,0,0,-1) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,2,0,0,-1) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,3,0,0,-1) endfunction // SouthWest function SetMeshMemblockGroundPlaneSouthWestPosition(Mesh ref as TMesh) SetMeshMemblockVertexPosition(Mesh.Memblock,0,Mesh.x,Mesh.y-Mesh.Size,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,1,Mesh.x,Mesh.y,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,2,Mesh.x,Mesh.y,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,3,Mesh.x,Mesh.y-Mesh.Size,Mesh.z) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,0,-1,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,1,-1,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,2,-1,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,3,-1,0,0) endfunction // NorthEast function SetMeshMemblockGroundPlaneNorthEastPosition(Mesh ref as TMesh) SetMeshMemblockVertexPosition(Mesh.Memblock,0,Mesh.x+Mesh.Size,Mesh.y-Mesh.Size,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,1,Mesh.x+Mesh.Size,Mesh.y,Mesh.z) SetMeshMemblockVertexPosition(Mesh.Memblock,2,Mesh.x+Mesh.Size,Mesh.y,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,3,Mesh.x+Mesh.Size,Mesh.y-Mesh.Size,Mesh.z+Mesh.Size) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,0,1,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,1,1,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,2,1,0,0) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,3,1,0,0) endfunction // NorthWest function SetMeshMemblockGroundPlaneNorthWestPosition(Mesh ref as TMesh) SetMeshMemblockVertexPosition(Mesh.Memblock,0,Mesh.x+Mesh.Size,Mesh.y-Mesh.Size,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,1,Mesh.x+Mesh.Size,Mesh.y,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,2,Mesh.x,Mesh.y,Mesh.z+Mesh.Size) SetMeshMemblockVertexPosition(Mesh.Memblock,3,Mesh.x,Mesh.y-Mesh.Size,Mesh.z+Mesh.Size) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,0,0,0,1) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,1,0,0,1) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,2,0,0,1) if Mesh.Normal = 1 then SetMeshMemblockVertexNormal(Mesh.Memblock,3,0,0,1) endfunction //---------------------------------------------------------------------- // create a randomized image for texture //---------------------------------------------------------------------- function GenImageTexture() HeaderSize = 3 * 4 ImageSize = 2 ^ 4 PixelCount = ImageSize ^ 2 ImageMemSize = HeaderSize + PixelCount * 4 Memblock = CreateMemblock(ImageMemSize) // write image data SetMemblockInt(Memblock,0,ImageSize) SetMemblockInt(Memblock,4,ImageSize) SetMemblockInt(Memblock,8,32) Alpha = 255 y = 1 x = 1 for i = 0 to PixelCount-1 Red = Random(50,200) Green = Random(50,200) Blue = Random(50,200) // for rg colorblind people set borders to ~grey if y = 1 then Red = 255 if y = ImageSize then Green = 255 if x = 1 then Red = 255 if x = ImageSize then Green = 255 SetMemblockByte(Memblock,HeaderSize+i*4+0,Red) SetMemblockByte(Memblock,HeaderSize+i*4+1,Green) SetMemblockByte(Memblock,HeaderSize+i*4+2,Blue) SetMemblockByte(Memblock,HeaderSize+i*4+3,Alpha) inc x if x > ImageSize inc y x = 1 endif next i endfunction memblock //---------------------------------------------------------------------- // create a full randomized clustered map //---------------------------------------------------------------------- // Textures type TTextureSet Ground as integer[TexMax] Cliff as integer[TexMax] endtype // data of each map tile type TTile Enabled as integer endtype // data of each cluster type TCluster Object as integer[0] // meshed object of the cluster endtype // data of the map type TMap // array size sx as integer // size of map x sy as integer // size of map y sz as integer // size of map z csx as integer // size of one cluster x csz as integer // size of one cluster z ccx as integer // size of one cluster x ccz as integer // size of one cluster z // world definition ts as float // tile size in world units // world view options ClipHeight as integer // cluster is only visible up to this height // world data Tile as TTile[0,0,0] Cluster as TCluster[0,0] endtype //---------------------------------------------------------------------- // set map an cluster size //---------------------------------------------------------------------- function SetMapSize(Map ref as TMap,MapX,MapY,MapZ,CX,CZ) Map.sx = MapX Map.sy = MapY Map.sz = MapZ Map.csx = CX Map.csz = CZ // set cluster count Map.ccx = Floor(Map.sx / Map.csx) Map.ccz = Floor(Map.sz / Map.csz) // if map tile count bigger then the cluster count recalc map tile count if Map.sx / Map.csx > Map.ccx then Map.sx = Map.ccx * Map.csx if Map.sz / Map.csz > Map.ccz then Map.sz = Map.ccz * Map.csz // if array to small if Map.sx <> Map.Tile.Length Map.Tile.Length = Map.sx endif for x = 0 to Map.sx - 1 if Map.sy <> Map.Tile[x].Length Map.Tile[x].Length = Map.sy endif next x for x = 0 to Map.sx - 1 for y = 0 to Map.sy - 1 if Map.sz <> Map.Tile[x,y].Length Map.Tile[x,y].Length = Map.sz endif next y next x if Map.ccx <> Map.Cluster.Length Map.Cluster.Length = Map.ccx endif for x = 0 to Map.ccx - 1 if Map.ccz <> Map.Cluster[x].Length Map.Cluster[x].Length = Map.ccz endif next x for x = 0 to Map.ccx - 1 for z = 0 to Map.ccz - 1 if Map.sy <> Map.Cluster[x,z].Object.Length Map.Cluster[x,z].Object.Length = Map.sy endif next z next x EndFunction //---------------------------------------------------------------------- // generate a flat terrain //---------------------------------------------------------------------- function GenerateTerrain(Map ref as TMap) for x = 0 to Map.sx - 1 for z = 0 to Map.sz - 1 for y = 0 to Map.sy - 1 if y = 0 Map.Tile[x,y,z].Enabled = 1 else Map.Tile[x,y,z].Enabled = 0 endif next y next z next x endfunction //---------------------------------------------------------------------- // generate highmap noise for terrain //---------------------------------------------------------------------- function GenerateNoise(Map ref as TMap) if MountainNoise > 0 for x = 0 to Map.sx - 1 for z = 0 to Map.sz - 1 for y = 0 to Map.sy - 1 if y > 0 if Map.Tile[x,y-1,z].Enabled = 1 if random(0,MountainNoise) = MountainNoise Map.Tile[x,y,z].Enabled = 1 endif endif endif next y next z next x endif endfunction // --------------------------------------------------------------------------------- // generate a large mountain // --------------------------------------------------------------------------------- Function GenerateMountain(Map Ref As TMap) Local x As Integer Local y As Integer Local x1 As Integer Local x2 As Integer Local y1 As Integer Local y2 As Integer Local s1 As Float Local s2 As Float Local h As Integer Local h1 As Integer Local h2 As Integer Local r As Integer Local rh As Integer Local r1 As Integer Local r2 As Integer Local xt As Integer Local yt As Integer Local i As Integer Local j As Integer Local k As Integer Local l As Integer // Initialwerte setzen x1 = Random(0,Map.sx-2) y1 = Random(0,Map.sz-2) x2 = Random(2,Floor(Map.sx/3)) y2 = Random(2,Floor(Map.sz/3)) If x1 > Map.sx / 2 x2 = x1 - x2 Else x2 = x1 + x2 EndIf If y1 > Map.sz / 2 y2 = y1 - y2 Else y2 = y1 + y2 EndIf If x1 > x2 x = x1 x1 = x2 x2 = x EndIf If y1 > y2 y = y1 y1 = y2 y2 = y EndIf s1 = (y2 - y1) / (x2 - x1) If s1 = 0 Then s1 = 0.1 s2 = y1 - x1 * s1 h1 = Floor(MountainHeight * Map.sy / 100) h2 = h1 + Map.sy h = Random(1,h1) If h < 1 Then h = 1 If h > Map.sy - 1 Then h = Map.sy - 1 r1 = 3 r2 = r1 + Floor(MountainExpansion*50/100) r = Random(r1,r2) // Berge zeichnen If x2 - x1 > y2 - y1 For i = x1 To x2 For k = 1 To h rh = Random(1,1+Floor(r/k)) If rh > 1 For j = -rh To rh For l = -rh To rh r1 = 0 If j < 0 Then r1 = -1 * Random(0,Abs(j)) If j > 0 Then r1 = Random(0,j) r2 = 0 If l < 0 Then r2 = -1 * Random(0,Abs(l)) If l > 0 Then r2 = Random(0,l) xt = i+r1 yt = Floor(s1*i+s2)+r2 if xt >= 0 and xt < Map.sx if k >= 0 and k < Map.sy if yt >= 0 and yt < Map.sz if k = 0 Map.Tile[xt,k,yt].Enabled = 1 else if Map.Tile[xt,k-1,yt].Enabled = 1 Map.Tile[xt,k,yt].Enabled = 1 endif endif endif endif endif Next l Next j EndIf Next k Next i Else For i = y1 To y2 For k = 1 To h rh = Random(1,1+Floor(r/k)) If rh > 1 For j = -rh To rh For l = -rh To rh r1 = 0 If j < 0 Then r1 = -1 * Random(1,Abs(j)) If j > 0 Then r1 = Random(1,j) r2 = 0 If l < 0 Then r2 = -1 * Random(1,Abs(l)) If l > 0 Then r2 = Random(1,l) xt = Floor((i-s2)/s1)+r2 yt = i+r1 if xt >= 0 and xt < Map.sx if k >= 0 and k < Map.sy if yt >= 0 and yt < Map.sz if k = 0 Map.Tile[xt,k,yt].Enabled = 1 else if Map.Tile[xt,k-1,yt].Enabled = 1 Map.Tile[xt,k,yt].Enabled = 1 endif endif endif endif endif Next l Next j EndIf Next k Next i EndIf EndFunction //---------------------------------------------------------------------- // create the selected cluster object //---------------------------------------------------------------------- function CreateClusterObject(Map ref as TMap,x,y,z,Textures as TTextureSet) MultiMeshObject = 0 // single mesh as template TempMesh as TMesh // activate all attributes TempMesh.Normal = 1 TempMesh.UV = 1 TempMesh.Color = 1 TempMesh.Size = Map.ts // create the Memblock if SetMeshMemblockHeader(TempMesh) = 0 SetMeshMemblockSimplePlane(TempMesh) // set all meshes for cluster for cix = 0 to Map.csx - 1 for ciz = 0 to Map.csz - 1 // draw only if top tile drawtile = 0 if y < Map.sy - 1 if Map.Tile[x * Map.csx + cix, y, z * Map.csz + ciz].Enabled = 1 if Map.Tile[x * Map.csx + cix, y + 1, z * Map.csz + ciz].Enabled = 0 drawtile = 1 endif endif else if Map.Tile[x * Map.csx + cix,y,z * Map.csz + ciz].Enabled = 1 drawtile = 1 endif endif TempMesh.x = cix * TempMesh.Size TempMesh.y = 0 TempMesh.z = ciz * TempMesh.Size if drawtile = 1 // set up the ground // set position of mesh ground plane in the object SetMeshMemblockGroundPlanePosition(TempMesh) // set the multi mesh object if MultiMeshObject = 0 // create the object with the first mesh with index 1 MultiMeshObject = CreateObjectFromMeshMemblock(TempMesh.Memblock) else // add mesh with with next index AddObjectMeshFromMemblock(MultiMeshObject,TempMesh.Memblock) endif if MultiMeshObject > 0 // set texture for plane ground MeshCount = GetObjectNumMeshes(MultiMeshObject) Texture = Textures.Ground[Random(0,Textures.Ground.Length - 1)] SetObjectMeshImage(MultiMeshObject,Meshcount,Texture,0) SetObjectMeshCastShadow(MultiMeshObject,Meshcount,1) endif endif // set up the cliff if y > 0 if Map.Tile[x * Map.csx + cix, y, z * Map.csz + ciz].Enabled = 1 // south east cliff if z * Map.csz + ciz > 0 if Map.Tile[x * Map.csx + cix, y, z * Map.csz + ciz - 1].Enabled = 0 SetMeshMemblockGroundPlaneSouthEastPosition(TempMesh) if MultiMeshObject = 0 MultiMeshObject = CreateObjectFromMeshMemblock(TempMesh.Memblock) else AddObjectMeshFromMemblock(MultiMeshObject,TempMesh.Memblock) endif MeshCount = GetObjectNumMeshes(MultiMeshObject) Texture = Textures.Cliff[Random(0,Textures.Cliff.Length - 1)] SetObjectMeshImage(MultiMeshObject,Meshcount,Texture,0) SetObjectMeshCastShadow(MultiMeshObject,Meshcount,1) endif endif // south west cliff if x * Map.csx + cix > 0 if Map.Tile[x * Map.csx + cix - 1, y, z * Map.csz + ciz].Enabled = 0 SetMeshMemblockGroundPlaneSouthWestPosition(TempMesh) if MultiMeshObject = 0 MultiMeshObject = CreateObjectFromMeshMemblock(TempMesh.Memblock) else AddObjectMeshFromMemblock(MultiMeshObject,TempMesh.Memblock) endif MeshCount = GetObjectNumMeshes(MultiMeshObject) Texture = Textures.Cliff[Random(0,Textures.Cliff.Length - 1)] SetObjectMeshImage(MultiMeshObject,Meshcount,Texture,0) SetObjectMeshCastShadow(MultiMeshObject,Meshcount,1) endif endif // north east cliff if x * Map.csx + cix < Map.sx - 1 if Map.Tile[x * Map.csx + cix + 1, y, z * Map.csz + ciz].Enabled = 0 SetMeshMemblockGroundPlaneNorthEastPosition(TempMesh) if MultiMeshObject = 0 MultiMeshObject = CreateObjectFromMeshMemblock(TempMesh.Memblock) else AddObjectMeshFromMemblock(MultiMeshObject,TempMesh.Memblock) endif MeshCount = GetObjectNumMeshes(MultiMeshObject) Texture = Textures.Cliff[Random(0,Textures.Cliff.Length - 1)] SetObjectMeshImage(MultiMeshObject,Meshcount,Texture,0) SetObjectMeshCastShadow(MultiMeshObject,Meshcount,1) endif endif // north west cliff if z * Map.csz + ciz < Map.sz - 1 if Map.Tile[x * Map.csx + cix, y, z * Map.csz + ciz + 1].Enabled = 0 SetMeshMemblockGroundPlaneNorthWestPosition(TempMesh) if MultiMeshObject = 0 MultiMeshObject = CreateObjectFromMeshMemblock(TempMesh.Memblock) else AddObjectMeshFromMemblock(MultiMeshObject,TempMesh.Memblock) endif MeshCount = GetObjectNumMeshes(MultiMeshObject) Texture = Textures.Cliff[Random(0,Textures.Cliff.Length - 1)] SetObjectMeshImage(MultiMeshObject,Meshcount,Texture,0) SetObjectMeshCastShadow(MultiMeshObject,Meshcount,1) endif endif endif endif next ciz next cix DeleteMemblock(TempMesh.Memblock) if MultiMeshObject > 0 SetObjectPosition(MultiMeshObject,x * Map.csx * TempMesh.Size,y * TempMesh.Size,z * Map.csz * TempMesh.Size) SetObjectCollisionMode(MultiMeshObject,0) SetObjectCullMode(MultiMeshObject,1) SetObjectLightMode(MultiMeshObject,1) SetObjectCastShadow(MultiMeshObject,1) SetObjectFogMode(MultiMeshObject,1) endif endif endfunction MultiMeshObject //---------------------------------------------------------------------- // build a map from scratch //---------------------------------------------------------------------- function Build(Map ref as TMap,Textures as TTextureSet) for x = 0 to Map.ccx - 1 for z = 0 to Map.ccz - 1 for y = 0 to Map.sy - 1 Map.Cluster[x,z].Object[y] = CreateClusterObject(Map,x,y,z,Textures) next y next z next x endfunction //---------------------------------------------------------------------- // set clipping position height //---------------------------------------------------------------------- Global ClipTime = 0 Global ClipRefresh = 0 function SetClipPosition(Map ref as TMap) If GetRawKeyPressed(KEY_PAGEUP) if Map.ClipHeight < Map.sy - 1 ClipTime = GetMilliseconds() inc Map.ClipHeight ClipRefresh = 1 endif endif If GetRawKeyPressed(KEY_PAGEDOWN) if Map.ClipHeight > 0 ClipTime = GetMilliseconds() dec Map.ClipHeight ClipRefresh = 1 endif endif if Now > ClipTime + 250 if ClipRefresh = 1 ClipTime = GetMilliseconds() for x = 0 to Map.ccx - 1 for z = 0 to Map.ccz - 1 for y = 0 to Map.sy - 1 if y > Map.ClipHeight SetObjectVisible(Map.Cluster[x,z].Object[y],0) else SetObjectVisible(Map.Cluster[x,z].Object[y],1) endif next y next z next x endif endif endfunction //---------------------------------------------------------------------- // create the world with the build functions //---------------------------------------------------------------------- Global TerrainMap as TMap TerrainMap.ts = TileSize TerrainMap.ClipHeight = WorldY - 1 SetMapSize(TerrainMap,WorldX,WorldY,WorldZ,ClusterX,ClusterZ) Global TextureSet as TTextureSet Print("generate Textures") for i = 0 to TextureSet.Ground.Length - 1 ImageMemblock = GenImageTexture() TextureSet.Ground[i] = CreateImageFromMemblock(ImageMemblock) DeleteMemblock(ImageMemblock) next i for i = 0 to TextureSet.Cliff.Length - 1 ImageMemblock = GenImageTexture() TextureSet.Cliff[i] = CreateImageFromMemblock(ImageMemblock) DeleteMemblock(ImageMemblock) next i Print("generate Map") sync() GenerateTerrain(TerrainMap) GenerateNoise(TerrainMap) Print("genrate Mountains") sync() for i = 1 to MountainCount GenerateMountain(TerrainMap) next i Print("build Map") sync() Build(TerrainMap,TextureSet) //---------------------------------------------------------------------- // set up the skybox and sun //---------------------------------------------------------------------- SetSunActive(1) SetSunColor(255,215,0) SetSunDirection(-1,-0.25,-1) SetSkyBoxSunColor(255,255,0) SetSkyBoxSunVisible(1) SetSkyBoxVisible(1) SetShadowMappingMode(1) SetFogMode(1) SetFogRange(75,1500) SetFogColor(200,200,200) SetFogSunColor(255,215,0) //---------------------------------------------------------------------- // set up the camera //---------------------------------------------------------------------- SetCameraRotation(1,CamAngle,45,0) SetCameraPosition(1,-10,CamHeight,-10) SetCameraRange(1,1,CamRange) //---------------------------------------------------------------------- // move camera //---------------------------------------------------------------------- #constant NORTH 0 #constant EAST 1 #constant SOUTH 2 #constant WEST 3 global CamMoveX = CamStep global CamMoveZ = CamStep global CamTime = 0 function MoveCam() if now > CamTime + CamDelay CamTime = GetMilliseconds() Select CamQuarter Case NORTH If GetRawKeyState(KEY_W) or GetRawKeyState(KEY_UP) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf If GetRawKeyState(KEY_S) or GetRawKeyState(KEY_DOWN) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf If GetRawKeyState(KEY_D) or GetRawKeyState(KEY_RIGHT) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf If GetRawKeyState(KEY_A) or GetRawKeyState(KEY_LEFT) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf EndCase Case EAST If GetRawKeyState(KEY_W) or GetRawKeyState(KEY_UP) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf If GetRawKeyState(KEY_S) or GetRawKeyState(KEY_DOWN) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf If GetRawKeyState(KEY_D) or GetRawKeyState(KEY_RIGHT) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf If GetRawKeyState(KEY_A) or GetRawKeyState(KEY_LEFT) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf EndCase Case SOUTH If GetRawKeyState(KEY_W) or GetRawKeyState(KEY_UP) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf If GetRawKeyState(KEY_S) or GetRawKeyState(KEY_DOWN) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf If GetRawKeyState(KEY_D) or GetRawKeyState(KEY_RIGHT) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf If GetRawKeyState(KEY_A) or GetRawKeyState(KEY_LEFT) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf EndCase Case WEST If GetRawKeyState(KEY_W) or GetRawKeyState(KEY_UP) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf If GetRawKeyState(KEY_S) or GetRawKeyState(KEY_DOWN) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf If GetRawKeyState(KEY_D) or GetRawKeyState(KEY_RIGHT) SetCameraPosition(1,GetCameraX(1)+CamMoveX,GetCameraY(1),GetCameraZ(1)+CamMoveZ) EndIf If GetRawKeyState(KEY_A) or GetRawKeyState(KEY_LEFT) SetCameraPosition(1,GetCameraX(1)-CamMoveX,GetCameraY(1),GetCameraZ(1)-CamMoveZ) EndIf EndCase EndSelect endif endfunction // --------------------------------------------------------------------------------- // Rotate the Camera in Quarter // --------------------------------------------------------------------------------- Global CamQuarter = 0 function RotateCam() Local x AS Integer Local CenterPos As Integer Local CenterDistance As Integer Local CenterX As Integer Local CenterZ As Integer Local NewPositionX As Integer Local NewPositionZ As Integer Local RotateCamera As Integer // aktuelle Position ermitteln CenterPos = Round(CamAngle*Tan(45)) CenterDistance = Sqrt((2*CenterPos)^2) Select CamQuarter Case NORTH CenterX = GetCameraX(1) + CenterDistance CenterZ = GetCameraZ(1) + CenterDistance EndCase Case EAST CenterX = GetCameraX(1) + CenterDistance CenterZ = GetCameraZ(1) - CenterDistance EndCase Case SOUTH CenterX = GetCameraX(1) - CenterDistance CenterZ = GetCameraZ(1) - CenterDistance EndCase Case WEST CenterX = GetCameraX(1) - CenterDistance CenterZ = GetCameraZ(1) + CenterDistance EndCase EndSelect // Abfrage Kamera rotieren RotateCamera = 0 If GetRawKeyPressed(KEY_E) = 1 Inc CamQuarter If CamQuarter > 3 Then CamQuarter = 0 RotateCamera = 1 EndIf If GetRawKeyPressed(KEY_Q) = 1 Dec CamQuarter If CamQuarter < 0 Then CamQuarter = 3 RotateCamera = 1 EndIf If RotateCamera = 1 // neuen Winkel berechnen x = 45+90*CamQuarter If x > 180 Then x = x - 360 If x < 180 Then x = x + 360 SetCameraRotation(1,CamAngle,x,0) // Entfernung berechnen Select CamQuarter Case NORTH NewPositionX = CenterX - CenterDistance NewPositionZ = CenterZ - CenterDistance EndCase Case EAST NewPositionX = CenterX - CenterDistance NewPositionZ = CenterZ + CenterDistance EndCase Case SOUTH NewPositionX = CenterX + CenterDistance NewPositionZ = CenterZ + CenterDistance EndCase Case WEST NewPositionX = CenterX + CenterDistance NewPositionZ = CenterZ - CenterDistance EndCase EndSelect // neue Kamera Position setzen SetCameraPosition(1,NewPositionX,CamHeight,NewPositionZ) EndIf EndFunction // --------------------------------------------------------------------------------- // Main Function // --------------------------------------------------------------------------------- global Ende = 0 global Now = 0 Function Main() Now = GetMilliseconds() // take frame time SetClearColor(0,0,0) //ClearScreen() Print( ScreenFPS() ) MoveCam() RotateCam() SetClipPosition(TerrainMap) // reduce Framerate manually //Wait = Floor(Now + 100 - GetMilliseconds()) //If Wait > 0 Then Sleep(Wait) //Update3D() //Render3D() //Render2DFront() //Swap() // manually swap backbuffer, Swap Sleeptime automatic with SyncRate > 0 Sync() If GetRawKeyPressed(KEY_ESCAPE) Then Ende = 1 // global ende of prog EndFunction // --------------------------------------------------------------------------------- // Main Loop // --------------------------------------------------------------------------------- While not Ende Main() EndWhile